async.waterfall的实现

waterfall和series函数都是按照顺序执行,不同之处是waterfall每个函数产生的值都可以传递给下一个函数,series不可以。

实现

// util.js

module.exports = {
    noop() { },

    restArgs: function (fn, startIdx) {
        // fn为传进来的的函数
        startIdx = startIdx == null ? fn.length - 1 : +startIdx;

        return function () {
            let len = Math.max(arguments.length - startIdx, 0),
                rest = new Array(len),
                i;

            for (i = 0; i < len; i++)
                rest[i] = arguments[i + startIdx];

            switch (startIdx) {
                case 0: return fn.call(this, rest);
                case 1: return fn.call(this, arguments[0], rest);
                case 2: return fn.call(this, arguments[0], arguments[1], rest);
            }

            let args = new Array(startIdx + 1);

            for(i=0;i<startIdx;i++)
                args[i] = arguments[i];

            args[startIdx] = rest;

            return fn.apply(this,args);
        }
    },

    waterfall: function (tasks, cb) {
        let self = this;
        cb = cb || noop;

        let current = 0;

        // taskCb是restArgs返回的匿名函数
        let taskCb = this.restArgs(function (err, args) {
            if (++current >= tasks.length || err) {
                args.unshift(err);
                process.nextTick(function () { cb.apply(null, args); cb = self.noop })
            } else {
                args.push(taskCb);
                tasks[current].apply(null, args)
            }
        })

        if (tasks.length) {
            // 此处的taskCb其实就是test.js里每个function里的cb()
            tasks[0](taskCb)
        } else {
            process.nextTick(function () { cb(null); cb = this.noop })
        }
    }
}

测试文件

//test

const util = require('./util')

util.waterfall([
    function(cb){
        setTimeout(()=>{
            cb(null, 'one','two','three','four')
        },1000);
    },
    function(args1,args2,args3,args4,cb){
        // args1 -> 'one'
        console.log(args1)
        console.log(args2)
        console.log(args3)
        console.log(args4)
        cb(null, 'done')
    }
],function(err, result){
    // result -> 'done'
    console.log(result)
})

测试结果

posted @ 2020-09-15 14:26  yatolk  阅读(786)  评论(0编辑  收藏  举报