tapable学习笔记之AsyncParallelHook
从tapable生产的脚本来看AsyncParallelHook
先来看 tap + callAsync
const { AsyncParallelHook} = require("tapable");let queue1 = new AsyncParallelHook(['name']);console.time('cost');queue1.tap('1', function (name) { console.log(name, 1);});queue1.tap('2', function (name) { console.log(name, 2);});queue1.callAsync('webpack', err => { console.timeEnd('cost');});// 执行结果webpack 1webpack cost: 4.520ms
看生产的源码就知道:这种模式属于顺序执行,一个报错立即回调:
"use strict";var _context;var _x = this._x;do { var _counter = 2; var _done = () => { _callback(); }; if (_counter <= 0) break; var _fn0 = _x[0]; var _hasError0 = false; try { _fn0(________name); } catch (_err) { _hasError0 = true; if (_counter > 0) { _callback(_err); _counter = 0; } } if (!_hasError0) { if (--_counter === 0) _done(); } if (_counter <= 0) break; var _fn1 = _x[1]; var _hasError1 = false; try { _fn1(________name); } catch (_err) { _hasError1 = true; if (_counter > 0) { _callback(_err); _counter = 0; } } if (!_hasError1) { if (--_counter === 0) _done(); }} while (false);
接着看 tapAsync + callAsync
let queue2 = new AsyncParallelHook(['name']);console.time('cost1');queue2.tapAsync('1', function (name, cb) { setTimeout(() => { console.log(name, 1); cb(); }, 1000);});queue2.tapAsync('2', function (name, cb) { setTimeout(() => { console.log(name, 2); cb(); }, 2000);});queue2.callAsync('webpack', () => { console.log('over'); console.timeEnd('cost1');});// 执行结果/* webpack 1webpack 2overtime: 3004.411ms*/
生产的源码如下:
"use strict";var _context;var _x = this._x;do { var _counter = 2; var _done = () => { _callback(); }; if (_counter <= 0) break; var _fn0 = _x[0]; _fn0(name, _err0 => { if (_err0) { if (_counter > 0) { _callback(_err0); _counter = 0; } } else { if (--_counter === 0) _done(); } }); if (_counter <= 0) break; var _fn1 = _x[1]; _fn1(name, _err1 => { if (_err1) { if (_counter > 0) { _callback(_err1); _counter = 0; } } else { if (--_counter === 0) _done(); } });} while (false);
最后看tappromis + promise
执行
const { AsyncParallelBailHook} = require("tapable");let queue3 = new AsyncParallelBailHook(['name']);console.time('cost3');queue3.tapPromise('1', function (name, cb) { return new Promise(function (resolve, reject) { setTimeout(() => { console.log(name, 1); resolve(); }, 1000); });});queue3.tapPromise('2', function (name, cb) { return new Promise(function (resolve, reject) { setTimeout(() => { console.log(name, 2); reject('wrong');// reject()的参数是一个不为null的参数时,最后的回调就不会再调用了 }, 2000); });});queue3.promise('webpack') .then(() => { console.log('over'); console.timeEnd('cost3'); }, () => { console.log('error'); console.timeEnd('cost3'); });// 执行结果:/* webpack 1webpack 2errorcost3: 2009.970mswebpack 3*/
源码:
"use strict";return new Promise((_resolve, _reject) => { var _sync = true; function _error(_err) { if (_sync) _resolve(Promise.resolve().then(() => { throw _err; })); else _reject(_err); }; var _context; var _x = this._x; var _results = new Array(2); var _checkDone = () => { for (var i = 0; i < _results.length; i++) { var item = _results[i]; if (item === undefined) return false; if (item.result !== undefined) { _resolve(item.result); return true; } if (item.error) { _error(item.error); return true; } } return false; } do { var _counter = 2; var _done = () => { _resolve(); }; if (_counter <= 0) break; var _fn0 = _x[0]; var _hasResult0 = false; var _promise0 = _fn0(name); if (!_promise0 || !_promise0.then) throw new Error('Tap function (tapPromise) did not return promise (returned ' + _promise0 + ')'); _promise0.then(_result0 => { _hasResult0 = true; if (_counter > 0) { if (0 < _results.length && (_result0 !== undefined && (_results.length = 1), (_results[0] = { result: _result0 }), _checkDone())) { _counter = 0; } else { if (--_counter === 0) _done(); } } }, _err0 => { if (_hasResult0) throw _err0; if (_counter > 0) { if (0 < _results.length && ((_results.length = 1), (_results[0] = { error: _err0 }), _checkDone())) { _counter = 0; } else { if (--_counter === 0) _done(); } } }); if (_counter <= 0) break; if (1 >= _results.length) { if (--_counter === 0) _done(); } else { var _fn1 = _x[1]; var _hasResult1 = false; var _promise1 = _fn1(name); if (!_promise1 || !_promise1.then) throw new Error('Tap function (tapPromise) did not return promise (returned ' + _promise1 + ')'); _promise1.then(_result1 => { _hasResult1 = true; if (_counter > 0) { if (1 < _results.length && (_result1 !== undefined && (_results.length = 2), (_results[1] = { result: _result1 }), _checkDone())) { _counter = 0; } else { if (--_counter === 0) _done(); } } }, _err1 => { if (_hasResult1) throw _err1; if (_counter > 0) { if (1 < _results.length && ((_results.length = 2), (_results[1] = { error: _err1 }), _checkDone())) { _counter = 0; } else { if (--_counter === 0) _done(); } } }); } } while (false); _sync = false;});