Skip to content

AsyncSeriesBailHook

AsyncSeriesBailHook 为异步串行执行的。和我们上面的 AsyncParallelHook 一样,通过使用 tapAsync 注册事件,通过 callAsync 触发事件,也可以通过 tapPromise 注册事件,使用 promise 来触发。

其与其他的 AsyncSeries[XX]hook 不同的地方在于跟 syncHook 系列的命名一样 这个也是如果事件处理函数执行时有一个返回值不为空(即返回值为 undefined),则跳过剩下未执行的事件处理函数(如类的名字,意义在于保险)

例子

js
const { AsyncSeriesBailHook } = require('tapable');

// 创建一个同步事件流实例对象
const h1 = new AsyncSeriesBailHook(['xxx', 'arg2']);

h1.intercept({
	call: (source, target, routesList) => {
		console.log('Starting to h1 routes');
	},
	register: tapInfo => {
		// tapInfo = { type: "promise", name: "GoogleMapsPlugin", fn: ... }
		console.log(`${tapInfo.name} is doing its job`);
		return tapInfo; // may return a new tapInfo object
	},
	tap: tap => {
		console.log(tap, '444444');
	},
});

// 添加同步事件A
h1.tapAsync('A', (name, age, done) => {
	setTimeout(() => {
		console.log('A', name, age, new Date().getSeconds());
		done(undefined, true);
	}, 2000);
});

// 添加同步事件B
h1.tapAsync('B', (name, age, done) => {
	setTimeout(() => {
		console.log('B', name, age, new Date().getSeconds());
		done();
	}, 2000);
});

// 添加同步事件C
h1.tapAsync('C', (name, age, done) => {
	setTimeout(() => {
		console.log('C', name, age, new Date().getSeconds());
		done();
	}, 2000);
});
// 添加同步事件F
h1.tapAsync(
	{
		name: 'F',
		before: 'D',
	},
	(name, age, done) => {
		setTimeout(() => {
			console.log('F', name, age, new Date().getSeconds());
			done();
		}, 2000);
	}
);
// 添加同步事件E
h1.tapAsync(
	{
		name: 'E',
		before: 'C',
	},
	(name, age, done) => {
		setTimeout(() => {
			console.log('E', name, age, new Date().getSeconds());
			done();
		}, 2000);
	}
);
// 添加同步事件D
h1.tapAsync('D', (name, age, done) => {
	setTimeout(() => {
		console.log('D', name, age, new Date().getSeconds());
		done();
	}, 2000);
});

// 执行这个事件流
h1.callAsync('立早', 20, () => {
	console.log('函数执行完毕');
});

结果为

[HMR] Waiting for update signal from WDS...
A is doing its job
B is doing its job
C is doing its job
F is doing its job
E is doing its job
D is doing its job

Starting to h1 routes
 {type: "async", fn: ƒ, name: "F", before: "D"} "444444"
 {type: "async", fn: ƒ, name: "A"} "444444"
 {type: "async", fn: ƒ, name: "B"} "444444"
 {type: "async", fn: ƒ, name: "E", before: "C"} "444444"
 {type: "async", fn: ƒ, name: "C"} "444444"
 {type: "async", fn: ƒ, name: "D"} "444444"

[WDS] Hot Module Replacement enabled.

F 立早 20 50
{type: "async", fn: ƒ, name: "A"} "444444"
A 立早 20 52

发现其秒数都是间隔 2 秒,那么说明所有的事件流是串行执行的,下一个事件流需要等待上一个事件流的完成才会执行。

其中在 A 中 done(undefined , 'gzhA'); 所以下面的就不执行了,其原理跟 SyncbailHook 是一样的, 如果如果事件处理函数执行时有一个返回值不为空(即返回值为 undefined),则跳过剩下未执行的事件处理函数

原理

this.content()

js
class AsyncSeriesBailHookCodeFactory extends HookCodeFactory {
	content({ onError, onResult, onDone }) {
		return this.callTapsSeries({
			onError: (i, err, next, doneBreak) => onError(err) + doneBreak(true),
			onResult: (i, result, next) => `if(${result} !== undefined) {\n${onResult(result)};\n} else {\n${next()}}\n`,
			onDone,
		});
	}
}

发现其直接通过 this.callTapsSeries()去生成可以执行的代码的

从上面的流程可以看出其整体的过程是其实跟 asyncSeriesHook 是一样的,只是在else{}的加入了

js
(_err0, _result0) => {
  if (_err0) {
		_callback(_err0);
	} else {
} else {
		if (_result0 !== undefined) {
			_callback(null, _result0);
		} else {
      // xxxxxxxxxxxxxxxxxxx
    }

}

如果传入的不为 undefined 的参数,那么就会直接 callback

全部伪代码
js
var _tap0 = _taps[0];
_interceptors[0].tap(_tap0);
var _fn0 = _x[0];
_fn0(xxx, arg2, (_err0, _result0) => {
	if (_err0) {
		_callback(_err0);
	} else {
		if (_result0 !== undefined) {
			_callback(null, _result0);
		} else {
			var _tap1 = _taps[1];
			_interceptors[0].tap(_tap1);
			var _fn1 = _x[1];
			_fn1(xxx, arg2, (_err1, _result1) => {
				if (_err1) {
					_callback(_err1);
				} else {
					if (_result1 !== undefined) {
						_callback(null, _result1);
					} else {
						var _tap2 = _taps[2];
						_interceptors[0].tap(_tap2);
						var _fn2 = _x[2];
						_fn2(xxx, arg2, (_err2, _result2) => {
							if (_err2) {
								_callback(_err2);
							} else {
								if (_result2 !== undefined) {
									_callback(null, _result2);
								} else {
									var _tap3 = _taps[3];
									_interceptors[0].tap(_tap3);
									var _fn3 = _x[3];
									_fn3(xxx, arg2, (_err3, _result3) => {
										if (_err3) {
											_callback(_err3);
										} else {
											if (_result3 !== undefined) {
												_callback(null, _result3);
											} else {
												var _tap4 = _taps[4];
												_interceptors[0].tap(_tap4);
												var _fn4 = _x[4];
												_fn4(xxx, arg2, (_err4, _result4) => {
													if (_err4) {
														_callback(_err4);
													} else {
														if (_result4 !== undefined) {
															_callback(null, _result4);
														} else {
															var _tap5 = _taps[5];
															_interceptors[0].tap(_tap5);
															var _fn5 = _x[5];
															_fn5(xxx, arg2, (_err5, _result5) => {
																if (_err5) {
																	_callback(_err5);
																} else {
																	if (_result5 !== undefined) {
																		_callback(null, _result5);
																	} else {
																		_callback();
																	}
																}
															});
														}
													}
												});
											}
										}
									});
								}
							}
						});
					}
				}
			});
		}
	}
});

上次更新: