什么是async.waterfall的简单实现?

时间:2015-03-06 21:42:56

标签: javascript node.js asynchronous waterfall

我正在使用async library中的一些功能,并希望确保我了解他们在内部的工作方式;但是,我坚持async.waterfallimplementation here)。实际实现使用了库中的其他功能,没有太多经验,我发现很难遵循。

有人可以在不担心优化的情况下提供实现瀑布功能的 非常简单的 实现吗?可能与this answer相当。

来自the docs,瀑布的描述:

  

运行函数的tasks数组,每个函数都通过它们   结果到阵列中的下一个。但是,如果任何任务通过了   错误到自己的回调,下一个函数没有执行,并且   主要的回调会立即调用错误。

一个例子:

async.waterfall([
    function(callback) {
        callback(null, 'one', 'two');
    },
    function(arg1, arg2, callback) {
      // arg1 now equals 'one' and arg2 now equals 'two'
        callback(null, 'three');
    },
    function(arg1, callback) {
        // arg1 now equals 'three'
        callback(null, 'done');
    }
], function (err, result) {
    // result now equals 'done'    
});

1 个答案:

答案 0 :(得分:8)

嗯,这是一个通过排队来链接函数的简单实现。

首先,功能:

function waterfall(arr, cb){} // takes an array and a callback on completion

现在,我们需要跟踪数组并迭代它:

function waterfall(arr, cb){
    var fns = arr.slice(); // make a copy
}

让我们从处理传递和空数组开始,添加一个额外的参数,以便我们可以传递被称为result的结果:

function waterfall(arr, cb, result){ // result is the initial result
    var fns = arr.slice(); // make a copy
    if(fns.length === 0){
        process.nextTick(function(){ // don't cause race conditions
            cb(null, result); // we're done, nothing more to do
        });
    }
}

那太好了:

waterfall([], function(err, data){
    console.log("Done!");
});

现在,让我们处理其中的内容:

function waterfall(arr, cb, result){ // result is the initial result
    var fns = arr.slice(1); // make a copy, apart from the first element
    if(!arr[0]){ // if there is nothing in the first position
        process.nextTick(function(){ // don't cause race conditions
            cb(null, result); // we're done, nothing more to do
        });
        return;
    }
    var first = arr[0]; // get the first function
    first(function(err, data){ // invoke it
         // when it is done
         if(err) return cb(err); // early error, terminate entire call
         // perform the same call, but without the first function
         // and with its result as the result
         waterfall(fns, cb, data); 
    });
}

那就是它!我们通过基本上使用递归来克服我们无法循环回调的事实。 Here is a fiddle说明了这一点。

值得一提的是,如果我们使用promises实现它,我们就可以使用for循环。