上面这个例子主要就是用了tap和call这两个实例方法,其中tap接收两个参数,第一个是个字符串,并没有实际用处,仅仅是一个注释的作用,第二个参数就是一个回调函数,用来执行事件触发时的具体逻辑。
accelerate.tap("LoggerPlugin", (newSpeed) => console.log("LoggerPlugin", `加速到${newSpeed}`) );上述这种写法其实与,因为webpack的plguin就是用tapable实现的,第一个参数一般就是plugin的名字:
而call就是简单的触发这个事件,在webpack的plguin中一般不需要开发者去触发事件,而是webpack自己在不同阶段会触发不同的事件,比如beforeRun, run等等,plguin开发者更多的会关注这些事件出现时应该进行什么操作,也就是在这些事件上注册自己的回调。
SyncBailHook上面的SyncHook其实就是一个简单的发布订阅模式,SyncBailHook就是在这个基础上加了一点流程控制,前面我们说过了,Bail就是个保险,实现的效果是,前面一个回调返回一个不为undefined的值,就中断这个流程。比如我们现在将前面这个例子的SyncHook换成SyncBailHook,然后在检测超速的这个插件里面加点逻辑,当它超速了就返回错误,后面的DamagePlugin就不会执行了:
const { SyncBailHook } = require("tapable"); // 使用的是SyncBailHook // 实例化一个加速的hook const accelerate = new SyncBailHook(["newSpeed"]); accelerate.tap("LoggerPlugin", (newSpeed) => console.log("LoggerPlugin", `加速到${newSpeed}`) ); // 再注册一个回调,用来检测是否超速 // 如果超速就返回一个错误 accelerate.tap("OverspeedPlugin", (newSpeed) => { if (newSpeed > 120) { console.log("OverspeedPlugin", "您已超速!!"); return new Error('您已超速!!'); } }); accelerate.tap("DamagePlugin", (newSpeed) => { if (newSpeed > 300) { console.log("DamagePlugin", "速度实在太快,车子快散架了。。。"); } }); accelerate.call(500);然后再运行下看看:
可以看到由于OverspeedPlugin返回了一个不为undefined的值,DamagePlugin被阻断,没有运行了。
SyncWaterfallHookSyncWaterfallHook也是在SyncHook的基础上加了点流程控制,前面说了,Waterfall实现的效果是将上一个回调的返回值作为参数传给下一个回调。所以通过call传入的参数只会传递给第一个回调函数,后面的回调接受都是上一个回调的返回值,最后一个回调的返回值会作为call的返回值返回给最外层:
const { SyncWaterfallHook } = require("tapable"); const accelerate = new SyncWaterfallHook(["newSpeed"]); accelerate.tap("LoggerPlugin", (newSpeed) => { console.log("LoggerPlugin", `加速到${newSpeed}`); return "LoggerPlugin"; }); accelerate.tap("Plugin2", (data) => { console.log(`上一个插件是: ${data}`); return "Plugin2"; }); accelerate.tap("Plugin3", (data) => { console.log(`上一个插件是: ${data}`); return "Plugin3"; }); const lastPlugin = accelerate.call(100); console.log(`最后一个插件是:${lastPlugin}`);然后看下运行效果吧:
SyncLoopHookSyncLoopHook是在SyncHook的基础上添加了循环的逻辑,也就是如果一个插件返回true就会一直执行这个插件,直到他返回undefined才会执行下一个插件:
const { SyncLoopHook } = require("tapable"); const accelerate = new SyncLoopHook(["newSpeed"]); accelerate.tap("LoopPlugin", (newSpeed) => { console.log("LoopPlugin", `循环加速到${newSpeed}`); return new Date().getTime() % 5 !== 0 ? true : undefined; }); accelerate.tap("LastPlugin", (newSpeed) => { console.log("循环加速总算结束了"); }); accelerate.call(100);执行效果如下: