webpack核心模块tapable用法解析 (4)

image-20210309172537951

tapAsync和tapPromise混用

既然tapable支持这两种异步写法,那这两种写法可以混用吗?我们来试试吧:

const { AsyncParallelHook } = require("tapable"); const accelerate = new AsyncParallelHook(["newSpeed"]); console.time("total time"); // 记录起始时间 // 来一个promise写法 accelerate.tapPromise("LoggerPlugin", (newSpeed) => { return new Promise((resolve) => { // 1秒后加速才完成 setTimeout(() => { console.log("LoggerPlugin", `加速到${newSpeed}`); resolve(); }, 1000); }); }); // 再来一个async写法 accelerate.tapAsync("OverspeedPlugin", (newSpeed, done) => { // 2秒后检测是否超速 setTimeout(() => { if (newSpeed > 120) { console.log("OverspeedPlugin", "您已超速!!"); } done(); }, 2000); }); // 使用promise触发事件 // accelerate.promise(500).then(() => { // console.log("任务全部完成"); // console.timeEnd("total time"); // 记录总共耗时 // }); // 使用callAsync触发事件 accelerate.callAsync(500, () => { console.log("任务全部完成"); console.timeEnd("total time"); // 记录总共耗时 });

这段代码无论我是使用promise触发事件还是callAsync触发运行的结果都是一样的,所以tapable内部应该是做了兼容转换的,两种写法可以混用:

image-20210309173217034

由于tapAsync和tapPromise只是写法上的不一样,我后面的例子就全部用tapAsync了。

AsyncParallelBailHook

前面已经看了SyncBailHook,知道带Bail的功能就是当一个任务返回不为undefined的时候,阻断后面任务的执行。但是由于Parallel任务都是同时开始的,阻断是阻断不了了,实际效果是如果有一个任务返回了不为undefined的值,最终的回调会立即执行,并且获取Bail任务的返回值。我们将上面三个任务执行时间错开,分别为1秒,2秒,3秒,然后在2秒的任务触发Bail就能看到效果了:

const { AsyncParallelBailHook } = require("tapable"); const accelerate = new AsyncParallelBailHook(["newSpeed"]); console.time("total time"); // 记录起始时间 accelerate.tapAsync("LoggerPlugin", (newSpeed, done) => { // 1秒后加速才完成 setTimeout(() => { console.log("LoggerPlugin", `加速到${newSpeed}`); done(); }, 1000); }); accelerate.tapAsync("OverspeedPlugin", (newSpeed, done) => { // 2秒后检测是否超速 setTimeout(() => { if (newSpeed > 120) { console.log("OverspeedPlugin", "您已超速!!"); } // 这个任务的done返回一个错误 // 注意第一个参数是node回调约定俗成的错误 // 第二个参数才是Bail的返回值 done(null, new Error("您已超速!!")); }, 2000); }); accelerate.tapAsync("DamagePlugin", (newSpeed, done) => { // 3秒后检测是否损坏 setTimeout(() => { if (newSpeed > 300) { console.log("DamagePlugin", "速度实在太快,车子快散架了。。。"); } done(); }, 3000); }); accelerate.callAsync(500, (error, data) => { if (data) { console.log("任务执行出错:", data); } else { console.log("任务全部完成"); } console.timeEnd("total time"); // 记录总共耗时 });

可以看到执行到任务2时,由于他返回了一个错误,所以最终的回调会立即执行,但是由于任务3之前已经同步开始了,所以他自己仍然会运行完,只是已经不影响最终结果了:

image-20210311142451224

AsyncSeriesHook

AsyncSeriesHook是异步串行hook,如果有多个任务,这多个任务之间是串行的,但是任务本身却可能是异步的,下一个任务必须等上一个任务done了才能开始:

const { AsyncSeriesHook } = require("tapable"); const accelerate = new AsyncSeriesHook(["newSpeed"]); console.time("total time"); // 记录起始时间 accelerate.tapAsync("LoggerPlugin", (newSpeed, done) => { // 1秒后加速才完成 setTimeout(() => { console.log("LoggerPlugin", `加速到${newSpeed}`); done(); }, 1000); }); accelerate.tapAsync("OverspeedPlugin", (newSpeed, done) => { // 2秒后检测是否超速 setTimeout(() => { if (newSpeed > 120) { console.log("OverspeedPlugin", "您已超速!!"); } done(); }, 2000); }); accelerate.tapAsync("DamagePlugin", (newSpeed, done) => { // 2秒后检测是否损坏 setTimeout(() => { if (newSpeed > 300) { console.log("DamagePlugin", "速度实在太快,车子快散架了。。。"); } done(); }, 2000); }); accelerate.callAsync(500, () => { console.log("任务全部完成"); console.timeEnd("total time"); // 记录总共耗时 });

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfpzg.html