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 1
webpack
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 1
webpack 2
over
time: 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 1
webpack 2
error
cost3: 2009.970ms
webpack 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;
});