【问题标题】:Asynchronous calls inside loop [duplicate]循环内的异步调用[重复]
【发布时间】:2012-09-10 10:21:35
【问题描述】:

可能重复:
Coordinating parallel execution in node.js

首先,上手伪代码:

forEach(arrayelements) {
  asyncQueryFunction(function(qres) {
    //work with query results.
  });
}
// finally, AFTER all callbacks did return:
res.render("myview");

怎么做?

如果这还不够清楚,我会解释:

我需要执行一系列“更新”查询(在 mongodb 中,通过 mongoose),循环遍历文档 ID 列表。对于数组中的每个 id,我将调用一个异步函数,该函数将返回查询结果(实际上我不需要对它们做任何事情)。

我知道我必须使用.forEach() javascript 循环,但是只有当我的所有异步查询都完成时,我才能执行我的“最终”回调?

当我要执行“有限”系列任务时,我已经在使用出色的异步库 (https://github.com/caolan/async) 来完成此类任务。但我不认为我可以将一组不同的函数传递给它。

我可以吗?

【问题讨论】:

标签: node.js asynchronous express


【解决方案1】:

非常简单的模式是使用“正在运行的任务”计数器:

var numRunningQueries = 0
forEach(arrayelements) {
  ++numRunningQueries;
  asyncQueryFunction(function(qres) {
    //work with query results.
    --numRunningQueries;
    if (numRunningQueries === 0) {
       // finally, AFTER all callbacks did return:
       res.render("myview");
    }
  });
}

或者,或者,使用异步帮助程序库,例如 Async.js

【讨论】:

  • 假设我们在处理异步函数时在某个请求中有这段代码,假设我们再收到一个请求,在这种情况下 var numRunningQueries 不会被覆盖为 0 ?我
  • 它总是在调用前递增,在调用完成时递减。 node 中的 JS 是单线程的,这里不能有竞态条件
  • 但是 aync 函数在单独的线程中运行对吗?所以想像当我们完成数组但 aysnc 函数仍在处理时会发生什么,而且它是一个局部变量,所以我认为它会保留它的价值。我想太多了。
  • 不,他们没有。当您并行“运行”多个异步函数时,您实际上是在并行等待 io 而不是并行“执行”。这正是事件循环的目标——您只需要一个执行线程即可。
【解决方案2】:

如果我理解正确,asyncQueryFunction 总是相同的,因为您对每个文档应用相同的更新。

我使用辅助方法在保存(只是交换更新)多个猫鼬文档(从 CoffeeScript 转换,因此可能不完美)后回调:

function saveAll(docs, callback) {

  // a count for completed operations, and save all errors
  var count = 0
    , errors = [];

  if (docs.length === 0) {
    return callback();
  } else {
    for (var i = 0; i < docs.length; i++) {

      // instead of save, do an update, or asyncQueryFunction
      docs[i].save(function(err) {

        // increase the count in each individual callback
        count++;

        // save any errors
        if (err != null) {
          errors.push(err);
        }

        // once all the individual operations have completed,
        // callback, including any errors
        if (count === docs.length) {
          return callback(errors);
        }
      });
    }
  }
};

saveAll(arrayElements, function(errors) {
  // finally, AFTER all callbacks did return:
  res.render("myview");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-17
    • 2019-03-24
    • 1970-01-01
    • 1970-01-01
    • 2017-03-06
    • 2022-01-26
    • 2014-11-05
    • 2019-07-31
    相关资源
    最近更新 更多