Node.js 中 For 循环中的 async.waterfall
Posted
技术标签:
【中文标题】Node.js 中 For 循环中的 async.waterfall【英文标题】:async.waterfall in a For Loop in Node.js 【发布时间】:2015-10-26 06:16:40 【问题描述】:在for
循环中使用async.waterfall
时,for
循环似乎在嵌套的async.waterfall
完成其所有步骤之前迭代。如何避免这种情况?
for(var i = 0; i < users.length; i++ )
console.log(i)
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'
console.log('done')
);
输出
0
1
2
3
4
done
done
done
done
done
期望的输出
0
done
1
done
2
done
3
done
4
done
【问题讨论】:
for-loop 是一个同步工作块,它在 eventloop 队列上发布异步工作——那么为什么它需要以不同的顺序工作呢?也许澄清你的实际问题会给你一个更好的答案。 不要使用for
循环,而是使用async.map
(或任何你需要的)
【参考方案1】:
您需要应用递归模式。我的建议是这样的
function foo(properties, callback)
/*Initialize inputs w/ useful defaults. Using a properties object simply because it looks nicer, you can use individual values if you'd like.*/
properties.start = properties.start || 0;
properties.end = properties.end || 10; //or any default length
properties.data = properties.data || [];
async.waterfall([
function(callback)
,
function(arg1, arg2, callback)
/* arg1 now equals 'one' and arg2 now equals 'two' you can do something with that before continuing processing */
,
function(arg1, callback)
/* arg1 now equals 'three', you can do something with that before continuing processing */
], function (err, result)
// result now equals 'done'
// now that we have fully processed one record, we need to either finish or recurse to the next element.
if(properties.index >= properties.end)
callback();
else
properties.index++;
foo(properties, callback);
)
我已将回调传递给每个函数回调。如果你愿意,你可以选择以这种方式提前结束递归,或者你可以在那个地方做任何你想做的事情。这类似于我最近提出的一个问题:Patterns for asynchronous but sequential requests,它也有一些其他有趣的解决方案。
【讨论】:
当async
库已经可用时,为什么要使用递归?
个人喜好。如果异步库在语言级别上进行了优化,它实际上可能性能更高(这个例子效率很低,但我想说明递归的概念而不是想炫耀我的能力)。还没有真正深入研究过那个库中的代码,我很难说。
我怀疑 async.js 的性能会更好,而且库代码确实很糟糕,但使用它的代码会更具可读性。
我不知道更具可读性,这只是一个调用来执行遍历数组的任务。也就是说,开发人员有责任维护这一点并在未来的任何变化中看到它。这绝对是使用异步库的充分理由。 TBH,我不知道异步库可以在这样的数据结构级别上做到这一点。正如我之前提到的,我还没有花时间学习它。【参考方案2】:
你可以像这样使用 async 的 forEachLimit
var async = require("async")
var users = []; // Initialize user array or get it from DB
async.forEachLimit(users, 1, function(user, userCallback)
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'
console.log('done')
userCallback();
);
, function(err)
console.log("User For Loop Completed");
);
【讨论】:
谢谢!这是一个后续问题:***.com/questions/31815917/…以上是关于Node.js 中 For 循环中的 async.waterfall的主要内容,如果未能解决你的问题,请参考以下文章