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;});