【问题标题】:How to use a for loop and get back results using node?如何使用 for 循环并使用节点返回结果?
【发布时间】:2014-04-03 10:08:17
【问题描述】:

我正在尝试运行一个多次执行相同操作的脚本,但我不想在回调之后陷入编写回调的困境。我是 node.js 的初学者,所以我不确定这样做的正确方法。下面是我的代码:

exports.index = function (req,res) {
  /* some code */
  something.execute(this, that, function(results) {
    for (var i = 2; i <= 10; i++) {
      var nextPage = getNextPage(i);
    }
  }
}

function getNextPage(page) {
  something.execute(this, that, function(results) {
    return results;
  }
}

结果是返回未定义。我知道这与 getNextPage 在其余代码之后完成有关,因为节点是异步的,但我不确定解决这个问题的最佳方法是什么。

有什么建议吗?谢谢!

编辑:在 getNextPage 中添加了代码。我几乎正在为另外 9 个页面运行相同的代码。似乎我需要弄清楚如何强制 something.execute 循环运行。

【问题讨论】:

  • 另外,在您展示如何分配 result 之前,我们无法说出问题所在。
  • 你需要展示更多代码或解释更多你想要做什么。如果您建议 getNextPage() return undefined 那么您需要显示 getNextPage() 的代码
  • 听起来你知道你可以通过添加另一个回调来解决这个问题,但是你不愿意去那里。对抗“太多嵌套回调”的常见模式是使用多个“Promises”库中的任何一个。 github.com/kriskowal/q 就是其中之一。你可能想检查一下。 Promise 为您的异步调用添加了一些样板,但将它们与您的回调分离。
  • 我同意 Jason 的 promises 库建议作为避免嵌套回调忧郁的一般方法,我认为您会发现否则这是不可避免的(节点野兽的性质)。如果它可能有帮助,我昨天提供了一个answer 一个带有大量评论的 Q 承诺示例以及等效的非承诺版本。更一般地说,其他评论者是正确的,我们需要更多代码来提供任何真正的帮助。
  • +1 用于使用 Promise 进行流量控制。尽管对于分页信息,使用流将是我的首选方法。 npmjs.org/package/event-stream

标签: javascript node.js asynchronous callback


【解决方案1】:

我认为在节点中编码的多种方式/风格的最佳概述是Mixu's Node Book Ch 7 "Control Flow"。具体示例“7.2.1 控制流模式 #1:系列 - 异步 for 循环”和“7.2.2 控制流模式 #2:完全并行 - 异步、并行 for 循环”。我在这里为您粘贴了 7.2.1,因为许多 stackoverflow 用户不喜欢没有摘录的外部链接。

function async(arg, callback) {
  console.log('do something with \''+arg+'\', return 1 sec later');
  setTimeout(function() { callback(arg * 2); }, 1000);
}
function final() { console.log('Done', results); }

var items = [ 1, 2, 3, 4, 5, 6 ];
var results = [];

items.forEach(function(item) {
  async(item, function(result){
    results.push(result);
    if(results.length == items.length) {
      final();
    }
  })
})

【讨论】:

  • 这可能有效,但在语义上完全不同:它并行执行forEach 项。回到 OP 的代码,如果异步 getNextPage 依赖于之前调用的结果,那将是一个问题。 IMO,来自 Async.js 的 async.forEach 会更合适。它异步执行项目,但顺序执行。
  • 是的,确实如此。我的观点是,为了编写节点程序,您必须了解整个主题。因此,本书的链接。只有这么多次,我想为那些第一次遇到 javascript 的异步挑战的人发布答案。我个人可能会使用async.eachLimit,但我要传达的信息是,这是您必须了解的核心内容。
  • 我明白了。我真的很期待在 Node 和所有主要浏览器中对 JavaScript 中的 yield 提供全面的生产支持。它将使 JavaScript 中的异步编程变得轻而易举,就像在 C# 中使用 async/await 一样。
【解决方案2】:

试试async 模块。 async 提供了许多方便的异步控制流功能。以后,您将拥有编写自己的技能和信心。不过就目前而言:

var async = require('async');

function requestHandler(req, res) {
    var itemNumbers = ... // might depend on req; might not

    function getItem(itemNumber, callback) {
        // ... asynchronous function which calls back with (err, result)
    }

    function withResults(err, results) {
        if (err) {
            // handle the error
        } else {
            // respond normally
        }
    }

    async.map(itemNumbers, async, withResults);
}

async.map 将对itemNumbers 中的每个项目调用一次getItem。如果任何调用 getItem 回调并返回错误,async.map 将回调 withResults 并返回该错误。否则,async.map 将使用 null 回调 errgetItem 回调结果数组 results

【讨论】:

    猜你喜欢
    • 2019-09-16
    • 2018-11-06
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多