【问题标题】:Force callbacks to process synchronously?强制回调同步处理?
【发布时间】:2016-12-08 09:19:47
【问题描述】:

我正在使用以下代码:

for (var x = 1; x < 10000000; x++) {
    count++
    myObj.name = count
    ch.sendToQueue(queueName, new Buffer(JSON.stringify(myObj)));
}

如果我注释掉 sendToQueue 命令,它会在没有错误的情况下完成,如果我不注释它,我会收到错误:FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory。我相信这种情况正在发生,因为它将我的 sendToQueue 调用添加到回调队列中,这些调用会累积并占用内存,直到没有剩余内存为止。

有没有办法强制回调同步运行,以免它们累积?

我猜这可能不是 Node/JavaScript 的最佳用例,如果是这样的话,我希望得到确认。

我知道一种解决方案是将循环分成多个较小的循环,在这个特殊的用例中我不能这样做,它需要是一个长时间运行的循环。

【问题讨论】:

  • 什么是ch.sendToQueue?你有文件吗?
  • 它是用于添加到消息队列的 AMQP
  • 我们必须知道sendToQueue 是什么,并且可能查看代码以了解建议的内容。当你运行一个巨大的 for 循环时,你不允许其他 node.js 代码在 for 循环期间运行(甚至包括垃圾收集),所以事情可能会堆积起来。我们需要知道 sendToQueue 正在做什么以及可能有哪些其他处理选项来提供帮助。
  • 具体是哪个 amqp 库(请链接)?
  • 可能是amqplib?适合签名。有什么东西在消耗这些消息吗?因为如果不是,它们必须存储在某处,而且内存不足一点也不奇怪。

标签: javascript node.js


【解决方案1】:

是的,你是对的,正如@jfriend00 所说,如果sendToQueue 延迟,则在退出循环之前不会执行其他 JS 代码。不过,您可以将循环分块;像这样的东西应该可以工作。

function chunkedLoop(from, to, step, cb) {
  var i = 0;
  for (var i = 0; from < to && i < step; from++, i++) {
    cb(from);
  }
  if (from < to) {
    setTimeout(chunkedLoop.bind(null, from, to, step, cb));
  }
}

chunkedLoop(0, 10, 3, function(i) { console.log(i); });

每个step 项目都会运行一个setTimeout 以推迟循环的其余部分,从而允许进行任何其他处理。

【讨论】:

  • 跟进问题,如果我使循环足够大,我需要使超时时间更长,以允许队列完成。有没有办法查询队列中有多少东西,这样我就可以等待它耗尽,然后再开始下一次运行?
猜你喜欢
  • 2012-05-14
  • 1970-01-01
  • 2018-01-02
  • 1970-01-01
  • 2018-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多