webpack(二)-tapable

234 阅读2分钟

Tapable

webpack是事件流机制,它的核心就是tapable tapable类似于node的envent库,包括同步和异步的方法,核心原理依赖发布订阅模式。

const {
  SyncHook,
  SyncBailHook,
  SyncWaterfallHook,
  SyncLoopHook,
  AsyncParralleHook,
  AsyncParalleBailHook,,
  AsyncSeriesBailHook,
  AsyncSeriesWaterfallHook,
} = require('tapable');

代码示例

同步

SyncHook

// 同步
class Person {
   constructor(){
      this.hooks = {
        arch : new SyncHook(['name']),
      }
   }
   tap(){ // 注册监听函数
      this.hooks.arch.tap('eat', function(name){
         console.log(name);
      });
   }
   start(){
     this.hooks.arch.call();
   }
}
const Nancy = new Person();
Nancy.tap(); //注册 
Nancy.start(); //启动
//SyncHook 实现 同步
class SyncHook { 
   constructor(args) {
   		this.tasks = [];
   }
   tap(name, task){
   	this.tasks.push(task);
   }
   call(..args){
    this.tasks.forEach((task) => task(...args));
   }
}
let hook = new SyncHook(['name']);
hook.tap('eat', function(name){
  console.log(name);
});
hook.call('apple');

SyncBailHook

同步保险钩子给定一个条件决定是否向下执行

class Person {
   constructor(){
      this.hooks = {
        arch : new SyncBailHook(['name']),
      }
   }
   tap(){ // 注册监听函数
      this.hooks.arch.tap('eat', function(name){
         console.log(name);
         return '我不想吃了'
      });
   }
   start(){
     this.hooks.arch.call();
   }
}
const Nancy = new Person();
Nancy.tap(); //注册 
Nancy.start(); //启动
//SyncBailHook 实现 同步
class SyncBailHook { 
   constructor(args) {
   		this.tasks = [];
   }
   tap(name, task){
   	this.tasks.push(task);
   }
   call(..args){
    let value; // return value
    let index = 0; // first exec index
    do{
       value = this.tasks[index++](...args);
    } while(value=== undefined && this.tasks.length > index)
   }
}
let hook = new SyncBailHook(['name']);
hook.tap('eat', function(name){
  console.log(name);
  return '我不想吃了'
});
hook.call('apple');

SyncWaterfallHook

class Person {
   constructor(){
      this.hooks = {
        arch : new SyncWaterfallHook(['name']),
      }
   }
   tap(){ // 注册监听函数
      this.hooks.arch.tap('eat', function(name){
         console.log(name);
         return '我不想吃了'
      });
      this.hooks.arch.tap('sleep', function(data){
         console.log(data);
      });
   }
   start(){
     this.hooks.arch.call();
   }
}
const Nancy = new Person();
Nancy.tap(); //注册 
Nancy.start(); //启动
//SyncWaterfallHook 瀑布执行
class SyncWaterfallHook { 
   constructor(args) {
   		this.tasks = [];
   }
   tap(name, task){
   	this.tasks.push(task);
   }
   call(..args){
    let [first, ...others] = this.tasks;
    let value = first(...args);
    others.reducw((a,b)=>{
     b(a);
    }, value);
   }
}
let hook = new SyncBailHook(['name']);
hook.tap('eat', function(name){
  console.log(name);
  return '我不想吃了'
});
hook.tap('sleep', function(data){
  console.log(data);
  return '我困了'
});
hook.call('apple');

SyncLoopHook

//多次执行不返回undefined的方法

class Person {
   constructor(){
      this.index = 0;
      this.hooks = {
        arch : new SyncLoopHook(['name']),
      }
   }
   tap(){ // 注册监听函数
      this.hooks.arch.tap('eat', function(name){
         console.log(name);
         return  ++this.index === 3 ?'我不想吃了': undefined;
      });
      this.hooks.arch.tap('sleep', function(data){
         console.log(data);
      });
   }
   start(){
     this.hooks.arch.call();
   }
}
const Nancy = new Person();
Nancy.tap(); //注册 
Nancy.start(); //启动
//SyncLoopHook loop执行
class SyncLoopHook { 
   constructor(args) {
   		this.tasks = [];
   }
   tap(name, task){
   	this.tasks.push(task);
   }
   call(..args){
    this.tasks.forEach(task => {
     let value;
     do{
      value = task(...args)
     }while(value != undefined)
    });
   }
}
let hook = new SyncLoopHoo(['name']);
hook.tap('eat', function(name){
  console.log(name);
  return '我不想吃了'
});
hook.tap('sleep', function(data){
  console.log(data);
  return '我困了'
});
hook.call('apple');

异步

并行 串行 同时发送多个请求

AsyncParralleHook

// 同步
class Person {
   constructor(){
      this.hooks = {
        arch : new AsyncParralleHook(['name']),
      }
   }
   tap(){ // 注册监听函数
      this.hooks.arch.tapAsync('eat', function(name){
         console.log(name);
      });
   }
   start(){
     this.hooks.arch.callAsync(, ()=>{
      console.log('end');
     });
   }
}
const Nancy = new Person();
Nancy.tap(); //注册 
Nancy.start(); //启动
//AsyncParralleHook 实现
class AsyncParralleHook { 
   constructor(args) {
   		this.tasks = [];
   }
   tapAsync(name, task){
   	this.tasks.push(task);
   }
   callAsync(..args){
    let callBack = args.pop();
    let index = 0;
    function done(){
      index++;
      if(index == this.task.length){
      	callBack();
      }
    }
    this.tasks.forEach(task=>{
     task(...args, done);
    });
   }
}
let hook = new SyncHook(['name']);
hook.tapAsync('eat', function(name,func){
func();
  console.log(name);
});
hook.callAsync('apple',function()=>{
	console.log('end');
});

AsyncSeriesBailHook

//AsyncSeriesBailHook 实现
classAsyncSeriesBailHook { 
   constructor(args) {
   		this.tasks = [];
   }
   tapAsync(name, task){
   	this.tasks.push(task);
   }
   callAsync(..args){
   let index = 0;
   let callback = args.pop();
   let next = ()=>{
   let task = this.task[index++];
   task(...args,next);
   }
   next();
   }
}