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();
}
}