Javascript Node.js中的异步代码和循环?

Javascript Node.js中的异步代码和循环?,javascript,node.js,asynchronous,nonblocking,Javascript,Node.js,Asynchronous,Nonblocking,我已经对异步编程做了几个小时的研究,但我似乎无法理解Node中的这一个概念,所以我想知道这里是否有人可以帮助我 我编写了以下代码示例来返回/输出一个简单字符串,它是来自对象的字符串的串联: var itemCollection = { item1 : [{ foo : "bar" }, { foo : "bar" }, { foo : "bar" }], item2 : [{ foo : "bar" }, { foo : "bar" }, { foo : "bar" }],

我已经对异步编程做了几个小时的研究,但我似乎无法理解Node中的这一个概念,所以我想知道这里是否有人可以帮助我

我编写了以下代码示例来返回/输出一个简单字符串,它是来自对象的字符串的串联:

var itemCollection = {
    item1 : [{ foo : "bar" }, { foo : "bar" }, { foo : "bar" }],
    item2 : [{ foo : "bar" }, { foo : "bar" }, { foo : "bar" }],
    item3 : [{ foo : "bar" }, { foo : "bar" }, { foo : "bar" }]
}

var aString = "";

for(item in itemCollection){
    for (var i = 0; i < itemCollection[item].length; i++) {
        var anItem = itemCollection[item][i];

        //someFunctionThatDoesALongIOOperation takes an item as a param, plus a callback.
        someFunctionThatDoesALongIOOperation(anItem, function(dataBackFromThisFunction){
            // Do something with the data returned from this function
            aString += dataBackFromThisFunction.dataToAppend;
        });
    };
}

console.log(aString);
var itemCollection={
项目1:[{foo:bar},{foo:bar},{foo:bar}],
项目2:[{foo:bar},{foo:bar},{foo:bar}],
项目3:[{foo:bar},{foo:bar},{foo:bar}]
}
var aString=“”;
对于(itemCollection中的项目){
对于(var i=0;i
因此,据我所知,Javascript以外的语言将同步运行一些不执行操作的函数,脚本将以“阻塞模式”运行。这意味着aString的值将返回/输出正确的值

但是,由于节点异步运行,代码可以随时继续运行,任务可能无法按顺序完成。这是因为事件循环在节点中的工作方式。我想我明白了

这就是我的问题所在。如果我希望像在其他语言中一样,使用正确的值返回/输出值
aString
,我需要对代码示例中的循环做什么?或者用更专业的话来回答我的问题:让
aString
返回预期结果的正确方法是什么,这样当
aString
已经返回时,在脚本完成执行后,IO操作(运行时间更长)就不会完成

我希望我的问题有意义,如果没有,请让我知道,我会在适当的地方进行编辑


谢谢

由于应用于每个项目的函数是异步的,因此处理它们的循环也必须是异步的(同样,使用此循环结果的函数也必须是异步的)。查看此特定点的更多细节

有两种方法可以做到这一点(都使用包装所有讨厌的回调逻辑):

  • 每次执行一个异步操作,等待上一个操作完成,然后才能开始下一个操作。这可能与传统同步循环的运行方式最为相似。我们可以通过以下方式做到这一点:

  • 当然,如果我们不能真正获得异步代码的好处并同时执行许多事情,那么使用异步代码就没有什么意义。我们可以并行执行所有异步操作,然后在一个步骤中一次减少所有异步操作。我发现,如果处理每个项目都需要一些长时间的操作,比如网络I/O,那么这是非常好的,因为我们可以一次启动并等待许多请求。我们使用以下方法来实现这一目标:

    async.map(itemCollection, function(item, cb) {
        someFunctionThatDoesALongIOOperation(item, function(dataBackFromThisFunction) {
            cb(null, dataBackFromThisFunction.dataToAppend);
        });
    }, function(err, results) {
        var aString = results.join('');
    });
    

你想让代码异步吗?
Javascript以外的语言会运行一些同步操作的函数
-不一定-取决于函数的编码方式。js,实际上,它不仅是异步的,而且API也是,我们鼓励您将代码编写为异步的。为什么
map
reduce
而不是
每个
并行
reduce
是串行执行的,在特定应用程序中可能更具语义<选择代码>映射
,因为回调仅在所有操作完成时调用,并且可以在之后单独减少
每个
并行执行所有操作,因此结果的顺序仍然无法保证,
并行
可以等效于
映射
,但需要为数组中的每个元素使用单独的函数(并且之后仍然需要手动减少)。是的,对不起,这是指
系列
不是
每个
。是的,我明白你的建议。
系列
可以工作,但与
并行
一样,它旨在控制许多不同异步操作的流程,而不是在许多事情上应用相同的操作。
async.map(itemCollection, function(item, cb) {
    someFunctionThatDoesALongIOOperation(item, function(dataBackFromThisFunction) {
        cb(null, dataBackFromThisFunction.dataToAppend);
    });
}, function(err, results) {
    var aString = results.join('');
});