乐趣区

tapable学习笔记之AsyncSeriesHook

AsyncSeriesHook 异步串行

从 tapable 生产的脚本来看 AsyncSeriesHook

先来看 tapAsync+ callAsync

const {AsyncSeriesHook} = require("tapable");

let queue2 = new AsyncSeriesHook(['name']);
console.time('cost2');
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.tapAsync('3', function (name, cb) {setTimeout(() => {console.log(name, 3);
        cb();}, 3000);
});

queue2.callAsync('webpack', (err) => {console.log(err);
    console.log('over');
    console.timeEnd('cost2');
}); 
// 执行结果
/* 
webpack 1
webpack 2
webpack 3
undefined
over
cost2: 6019.621ms
*/

源码:

"use strict";
var _context;
var _x = this._x;

function _next1() {var _fn2 = _x[2];
    _fn2(name, _err2 => {if (_err2) {_callback(_err2);
        } else {_callback();
        }
    });
}

function _next0() {var _fn1 = _x[1];
    _fn1(name, _err1 => {if (_err1) {_callback(_err1);
        } else {_next1();
        }
    });
}
var _fn0 = _x[0];
_fn0(name, _err0 => {if (_err0) {_callback(_err0);
    } else {_next0();
    }
});

从以上看,特别简单,串行执行。

再看下 tap 加 callAsync

const {AsyncSeriesHook} = require("tapable");

// tap
let queue1 = new AsyncSeriesHook(['name']);
console.time('cost1');
queue1.tap('1', function (name) {console.log(1);
    return "Wrong";
});
queue1.tap('2', function (name) {console.log(2);
});
queue1.tap('3', function (name) {console.log(3);
});
queue1.callAsync('zfpx', err => {console.log(err);
    console.timeEnd('cost1');
});
// 执行结果
/* 
1
2
3
undefined
cost1: 3.933ms
*/

源码:

"use strict";
var _context;
var _x = this._x;
var _fn0 = _x[0];
var _hasError0 = false;
try {_fn0(name);
} catch (_err) {
    _hasError0 = true;
    _callback(_err);
}
if (!_hasError0) {var _fn1 = _x[1];
    var _hasError1 = false;
    try {_fn1(name);
    } catch (_err) {
        _hasError1 = true;
        _callback(_err);
    }
    if (!_hasError1) {var _fn2 = _x[2];
        var _hasError2 = false;
        try {_fn2(name);
        } catch (_err) {
            _hasError2 = true;
            _callback(_err);
        }
        if (!_hasError2) {_callback();
        }
    }
}

即 顺序执行,报错就提前执行总 callback

再来看:
tapPromise + promise

const {AsyncSeriesHook} = require("tapable");

let queue3 = new AsyncSeriesHook(['name']);
console.time('cost3');
queue3.tapPromise('1',function(name){return new Promise(function(resolve){setTimeout(function(){console.log(name, 1);
           resolve();},1000)
   });
});
queue3.tapPromise('2',function(name,callback){return new Promise(function(resolve){setTimeout(function(){console.log(name, 2);
            resolve();},2000)
    });
});
queue3.tapPromise('3',function(name,callback){return new Promise(function(resolve){setTimeout(function(){console.log(name, 3);
            resolve();},3000)
    });
});
queue3.promise('webapck').then(err=>{console.log(err);
    console.timeEnd('cost3');
});

// 执行结果
/* 
webapck 1
webapck 2
webapck 3
undefined
cost3: 6021.817ms
*/

源码:

"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;

    function _next1() {var _fn2 = _x[2];
        var _hasResult2 = false;
        var _promise2 = _fn2(name);
        if (!_promise2 || !_promise2.then)
            throw new Error('Tap function (tapPromise) did not return promise (returned' + _promise2 + ')');
        _promise2.then(_result2 => {
            _hasResult2 = true;
            _resolve();}, _err2 => {if (_hasResult2) throw _err2;
            _error(_err2);
        });
    }

    function _next0() {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;
            _next1();}, _err1 => {if (_hasResult1) throw _err1;
            _error(_err1);
        });
    }
    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;
        _next0();}, _err0 => {if (_hasResult0) throw _err0;
        _error(_err0);
    });
    _sync = false;
});

即返回的是一个 promise

退出移动版