最近项目中有了小伙伴儿用了 tapable 控制事件处理, 以前知道 tapable 还是通过 webpack, webpack 通过 tapable 将实现与流程解耦, 所有具体实现通过插件的形式存在,一个类似于 Node.js 中的 EventEmitter的库
一个最简单的栗子
一个同步钩子 SyncHook
const { SyncHook } = require('tapable');
const hook = new SyncHook(['name']);
hook.tap('hello', (name) => {
console.log(`hello ${name}`);
});
hook.tap('hello again', (name) => {
console.log(`hello ${name}, again`);
});
hook.call('world !');
// hello world !
// hello world !, again
我们执行 hook.call('world !')
时会依次执行前面 hook.tap(name, callback)
中的回调函数。通过 SyncHook
创建同步钩子,使用 tap
注册回调,再调用 call
来触发
另外也有很多同步钩子:
SyncBailHook
: 类似于 SyncHook,执行过程中注册的回调返回非 undefined 时就停止不在执行。SyncWaterfallHook
: 接受至少一个参数, 上一个注册的回调返回值会作为下一个注册的回调的参数。SyncLoopHook
: 有点类似 SyncBailHook, 但是是在执行过程中回调返回非 undefined 时继续再次执行当前的回调。
一个异步钩子 AsyncParallelHook
AsyncParallelHook
顾名思义是并行执行的异步钩子,当注册的所有异步回调都并行执行完毕之后再执行 callAsync
或者 promise
中的函数。
const { AsyncParallelHook } = require('tapable');
const hook = new AsyncParallelHook(['name']);
console.time('cost');
hook.tapAsync('hello', (name, cb) => {
setTimeout(() => {
console.log(`hello ${name}`);
cb();
}, 2000);
});
hook.tapPromise('hello again', (name) => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`hello ${name}, again`);
resolve();
}, 1000);
});
});
hook.callAsync('ahonn', () => {
console.log('done');
console.timeEnd('cost');
});
// hello ahonn, again
// hello ahonn
// done
// cost: 2008.609ms
// 或者通过 hook.promise() 调用
// hook.promise('ahonn').then(() => {
// console.log('done');
// console.timeEnd('cost');
// });
一个异步顺序钩子 AsyncSeriesHook
如果你想要顺序的执行异步函数的话,显然 AsyncParallelHook 是不适合的。所以 tapable 提供了另外一个基础的异步钩子: AsyncSeriesHook
const { AsyncSeriesHook } = require('tapable');
const hook = new AsyncSeriesHook(['name']);
console.time('cost');
hook.tapAsync('hello', (name, cb) => {
setTimeout(() => {
console.log(`hello ${name}`);
cb();
}, 2000);
});
hook.tapPromise('hello again', (name) => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`hello ${name}, again`);
resolve();
}, 1000);
});
});
hook.callAsync('ahonn', () => {
console.log('done');
console.timeEnd('cost');
});
// hello ahonn
// hello ahonn, again
// done
// cost: 3011.162ms
上面的示例代码与 AsyncParallelHook
的示例代码几乎相同,不同的是 hook
是通过 new AsyncSeriesHook()
实例化的
通过 AsyncSeriesHook
就能够顺序的执行注册的回调, 除此之外注册与触发的用法都是相同的
**同样的,异步钩子也有一些带流程控制的钩子: **
AsyncParallelBailHook
: 执行过程中注册的回调返回非undefined
时就会直接执行callAsync
或者promise
中的函数(由于并行执行的原因,注册的其他回调依然会执行)。AsyncSeriesBailHook
: 执行过程中注册的回调返回非undefined
时就会直接执行callAsync
或者promise
中的函数,并且注册的后续回调都不会执行。AsyncSeriesWaterfallHook
: 与SyncWaterfallHook
类似,上一个注册的异步回调执行之后的返回值会传递给下一个注册的回调。
文章还是白piao的香啊: https://segmentfault.com/a/1190000020146256