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

測試結果


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM