我正在使用async library中的一些功能,并希望确保我了解他们在内部的工作方式;但是,我坚持async.waterfall
(implementation 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'
});
答案 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循环。