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

标签 javascript node.js asynchronous nonblocking

我已经对异步编程进行了数小时的研究,但我似乎无法掌握 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);

因此,根据我的理解,Javascript 以外的语言将someFunctionThatDoesALongIOOperation 同步运行,并且脚本将以“阻塞模式”运行。这意味着值 aString 将以其正确的值返回/输出。

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

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

我希望我的问题有意义,如果没有,请告诉我,我会在适当的情况下进行编辑。

谢谢

最佳答案

由于应用于每个项目的函数是异步的,因此处理它们的循环也必须是异步的(同样,使用此循环结果的函数也必须是异步的)。查看Bob Nystrom's "What Color is Your Function?"有关这一点的更多见解。

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

  • 一次执行一个异步操作,等待前一个操作完成后,下一个操作才能开始。这可能与传统同步循环的运行方式最相似。我们可以用 async.reduce 来做到这一点:

    async.reduce(itemCollection, "", function(memo, item, callback) {
        someFunctionThatDoesALongIOOperation(item, function(dataBackFromThisFunction) {
            callback(null, memo + dataBackFromThisFunction.dataToAppend);
        });
    }, function(err, result) {
        var aString = result;
    });
    
  • 当然,如果我们没有真正获得异步代码的好处并同时执行许多事情,那么拥有异步代码就没有什么意义。我们可以并行执行所有异步操作,然后在一个步骤中一次性减少所有操作。我发现如果处理每个项目需要一些长时间操作(例如网络 I/O),这非常有用,因为我们可以立即启动并等待许多请求。我们使用async.map实现这一目标:

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

关于javascript - Node.js 中的异步代码和循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31600040/

相关文章:

javascript - 使用 jQuery 根据文本内容按特定顺序对 div 重新排序

c# - 。网。异步 HttpWebRequest 的最大数量

javascript - 在 Javascript 中触发 Keyup 事件

javascript - 如何使用 NodeJS 将变量传递给其他模块?

node.js - 在 Windows 7 中创建 Node js 安装快捷方式的回滚

node.js - 如何在 JEST 中的 express 中间件中测试 next()

异步执行与同步执行。有什么不同?

php - Laravel 异步请求最佳实践

javascript - 示例 jquery 获取 sibling 的索引/位置

javascript - 多个 HTML 文本区域一起调整大小