上一篇文章我们以SyncHook
为例讲解了tapable
对于钩子的内部处理逻辑,这篇文章会挨个讲解剩余每种钩子,会直接对照例子和生成的代码来帮助大家理解。
SyncBailHook
上一个回调函数的返回值如果不为空,后面的回调就再也不会执行,相当于被截断.
demo
1 | let queue = new SyncBailHook(['name']); |
执行结果
1 | webpack 1 |
生成函数
1 | function anonymous(name) { |
SyncLoopHook
只要某个监听的回调返回值不为空就会一直循环执行这个回调,直到返回空才会执行下一个回调.
demo
1 | let queue = new SyncLoopHook(['name']); |
执行结果
1 | tap1 count: 3 |
生成函数
1 | function anonymous(name) { |
SyncWaterfallHook
上一个回调函数的返回值如果不为空,就会传给下一个回调函数当做参数
demo
1 | let queue = new SyncWaterfallHook(['name']); |
运行结果
1 | webpack 1 |
生成函数
1 | function anonymous(name) { |
AsyncParallelBailHook
剩下的都是异步钩子了,每个钩子会讲述 3 种监听发布方式
tap - callAsync
tapAsync - callAsync
tapPromise - promise
tap - callAsync
只要前一个回调的返回值不为空或者抛异常,就会直接执行 callAsync 的回调,后续的 tap 回调不会被执行。
每个监听函数的执行应当都是同步的。
demo
1 | queue1.tap('1', function(name) { |
运行结果
1 | webpack 1 |
生成函数
1 | function anonymous(name, _callback) { |
tapAsync - callAsync
- 若
callback
被同步执行:只要前一个回调函数的callback
在调用时不传error/result
参数,在执行完后就会顺序执行后一个回调。若callback
在调用时传了非空error/result
参数,会直接执行callAsync
的回调,并将非空error/result
参数当做入参。 - 若
callback
被异步执行:上述情况会改变,若调用callback
时传了error/result
参数,在执行完后就会执行callAsync
的回调,只不过后续的回调因为是异步的,所以依然有机会执行,只不过callAsync
的回调只会执行一次
demo
1 | queue2.tapAsync('1', function(name, callback) { |
运行结果
1 | webpack 2 |
生成函数
1 | function anonymous(name, _callback) { |
tapPromise - promise
如果某个tapPromsie
的回调Promise resolve
或reject
的参数不为空,
会直接导致Hook.promise
得到resolve
或reject
,而不会等后面的tapPromise
回调得到resolve
或reject
只不过因为promise
是异步的,所以后续的promise
依然有机会执行,只不过Hook.promise
的then / catch
只会执行一次.
demo
1 | queue3.tapPromise('1', function(name) { |
运行结果
1 | webpack 1 |
生成函数
1 | function anonymous(name) { |
AsyncParallelHook
tap - callAsync
只要前一个回调函数不抛异常,在执行完后就会顺序执行后一个回调。若抛异常,会直接执行 callAsync 的回调,并将异常当做参数
demo
1 | console.time('cost'); |
运行结果
1 | webpack 1 |
生成函数
1 | function anonymous(name, _callback) { |
tapAsync -callAsync
- 若
callback
被同步执行:只要前一个回调函数的callback
在调用时不传error
参数,在执行完后就会顺序执行后一个回调。若callback
在调用时传了非空error
参数,会直接执行callAsync
的回调,并将非空error
参数当做入参。 - 若
callback
被异步执行:上述情况会改变,若调用callback
时传了error
参数,在执行完后就会执行callAsync
的回调,只不过后续的回调因为是异步的,所以依然有机会执行,只不过callAsync
的回调只会执行一次
demo
1 | queue2.tapAsync('1', function(name, callback) { |
运行结果
1 | webpack 1 |
生成函数
1 | function anonymous(name, _callback) { |
tapPromise - promise
若回调的 promise
被 resolve
,在执行完后就会顺序执行后一个回调,若 reject
了就会只会跳到 Hook.promise
的 catch
回调。只不过因为 promise
是异步的,所以后续的 promise
依然有机会执行,只不过 Hook.promise
的 then/catch
只会执行一次。
demo
1 | queue3.tapPromise('1', function(name) { |
运行结果
1 | webpack 1 |
生成函数
1 | function anonymous(name) { |
AsyncSeriesBailHook
tap - callAsync
callback
的返回值不为null
,或者回调抛出异常,就会直接执行callAsync
绑定的回调函数
demo
1 | queue1.tap('1', function(name) { |
运行结果
1 | 1 |
生成函数
1 | function anonymous(name, _callback) { |
tapAsync - callAsync
callback: (err, result) => any
注意和AsyncParallelBailHook-tapAsync-callAsync
的对比:
AsyncSeriesBailHook
是异步串行,callback
的err
或result
参数不为null
,不管是同步还是异步环境中执行的,都会直接执行callAsync
绑定的回调函数,会将callback
的参数携带过去,后续的tapAsync
不会被执行。AsyncParallelBailHook
是异步并行,如果callback
是在异步环境中被调用如被注释的setTimeout
,那么后续的tapAsync
回调依然有机会被调用
demo
1 | queue2.tapAsync('1', function(name, callback) { |
运行结果
1 | webpack 1 |
生成函数
1 | function anonymous(name, _callback) { |
tapPromise - promise
如果某个tapPromsie
的回调Promise resolve
或reject
的参数不为空,
会直接导致Hook.promise
得到resolve
或reject
,后续的tapPromise
回调没有机会执行.
注意和AsyncParallelBailHook-tapPromise-promise
的区别,一个是异步串行,一个是异步并行.
demo
1 | queue3.tapPromise('1', function(name) { |
运行结果
1 | webpack 1 |
生成函数
1 | function anonymous(name) { |
AsyncSeriesHook
tap - callAsync
不关心每个tap
回调参数的返回值,除非抛出异常会直接调用callAsync
的回调,此时后续tap
回调均不会执行
demo
1 | queue1.tap('1', function(name) { |
运行结果
1 | 1 |
生成函数
1 | function anonymous(name, _callback) { |
tapAsync - callAsync
只有执行了前一个tapAsync
回调里的callback
后,才会执行后一个tapAsync
的回调。
如果执行callback
时传入了非空值,会被当做时error
,
此时会跳过后续的tapAsync
回调,直接执行callAsync
的回调,并传入error
demo
1 | queue2.tapAsync('1', function(name, callback) { |
运行结果
1 | webpack 1 |
生成函数
1 | function anonymous(name, _callback) { |
tapPromise - promise
只有执行了前一个tapPromise
回调里的Promise resolve
后,才会执行后一个tapPromise
的回调Promise
。
如果Promsie reject
了,此时会跳过后续的tapPromise
回调,直接执行hook.promise
的then
回调,参数就是error
对象
demo
1 | queue3.tapPromise('1', function(name) { |
运行结果
1 | webapck 1 |
生成函数
1 | function anonymous(name) { |
AsyncSeriesWaterfallHook
tap - callAsync
上一个监听函数的返回值, 可以作为下一个监听函数的参数。 如果监听函数报错,直接执行callAsync
的回调,后续 tap 回调不会被执行
demo
1 | queue1.tap('1', function(name) { |
运行结果
1 | webpack 1 |
生成函数
1 | function anonymous(name, _callback) { |
tapAsync - callAsync
上一个监听函数callback
的第二个调用参数, 可以作为下一个监听函数的data
参数。
如果callback
的第一个参数不为空,会被当做error
参数,直接执行callAsync
的回调并传入error
,后续tapAsync
不会执行
demo
1 | queue2.tapAsync('1', function(name, callback) { |
运行结果
1 | 1: webpack |
生成函数
1 | function anonymous(name, _callback) { |
tapPromise - promise
上一个监听函数Promise
的resolve
结果, 可以作为下一个监听函数的data
参数。
如果调用了reject
,直接执行Hook.promise
的catch
回调,并传入reject
参数,后续tapPromsie
回调不会再执行
demo
1 | queue3.tapPromise('1', function(name) { |
运行结果
1 | 1: webpack |
生成函数
1 | function anonymous(name) { |