【问题标题】:Node: For-loop delay inside Promise-chain [duplicate]节点:Promise 链中的 For 循环延迟 [重复]
【发布时间】:2017-12-31 00:21:32
【问题描述】:

我的 Node 应用程序将发票数据发送到 API,我希望我的应用程序在每次发票发布后按顺序发送数据/等待一段时间,因为如果一秒钟内有超过 20 个请求,API 服务器会阻止请求。

我认为一种方法是在每次迭代后暂停 for 循环,但我不确定如何实现。

下面是我目前将“发票生成”-promises 推送到 for 循环中的数组,然后使用 Promise.all 解决它们的代码。

感谢所有 cmets。

    // First, get access token from the service API
    serviceAPI.auth().then((token) => {

    // Array for the invoice promises
    let invoicePromises = [];

    // Push promises to the array
    for (let i = 0; i < rowAmount; i++) {
        invoicePromises.push(serviceAPI.generate(i, sheetData[i], token));
    }

    return Promise.all(invoicePromises);

    }).then((results) => {
    console.log(results);
    return utils.sortReport(results); // Return sorted results
    }).catch((e) => { console.error(e)});

【问题讨论】:

  • 这是一种实际计量您对任何特定请求数/秒的请求的方法:Choose proper async method for batch processing with rate limiting
  • 请记住,高效可靠地管理每秒请求数并不像插入延迟那么简单。一种可靠且有效地将您保持在每秒请求数以下的算法需要对请求进行计数和计时,并使用计时器来安排何时可以发送下一个请求。
  • @jfriend00:感谢这些明智的话。我现在会努力学习的。
  • @jfriend00:是否可以在 Node 中重新创建您的函数,或者我是否真的需要使用异步库或类似的东西进行同步流?您的示例有助于理解这个想法,但我正在努力使其在 Node 中工作。
  • 我的 rateLimitMap() 函数在 node.js 中运行良好。要使用它,您只需要有一个要迭代的数组,有一个接受数组元素作为参数并返回承诺的函数,然后复制rateLimitMap() 函数。您可以只删除update() 函数以不执行任何操作或从rateLimitMap() 函数中删除对它的调用,因为这些调用只是为了显示演示中的进度。其他一切都只是可以在任何地方运行的通用 Javascript。

标签: javascript node.js promise delayed-execution


【解决方案1】:

而不是完全创建它们:

 for (let i = 0; i < rowAmount; i++) {
    invoicePromises.push(serviceAPI.generate(i, sheetData[i], token));
}
return Promise.all(invoicePromises);

可以建立一个接一个调用的 Promise 链:

 sheetData.reduce((promise, data, i) => promise.then(result => serviceAPI.generate(i, data, token).then(res => result.concat(res))), Promise.resolve([]));

不过,这有点像 Promise 地狱,所以让我们使用 async await 来代替:

return (async function(){
  const result;
  for (let i = 0; i < rowAmount; i++) {
    result.push(await serviceAPI.generate(i, sheetData[i], token));
   //optionally sth like await timer(1000);
  } 
 return result;
})();

【讨论】:

  • 谢谢!我会试试这些。
  • 这个序列一次一个。这甚至与每秒 20 个请求完全不同。如果给定的请求需要 5 毫秒,那么这将每秒启动 200 个请求(请求太多)。如果给定的请求需要 5 秒,那么这将每 5 秒只启动一个请求(请求太少)。因此,这并不能真正衡量需要衡量什么才能高效并安全地保持在最大请求/秒以下。
  • @jfriend00 好的,然后stackoverflow.com/questions/47967232/…
【解决方案2】:

要让 nodejs 应用稍等片刻然后继续运行,您可以使用 sleep 模块轻松完成此操作。

第一:npm install sleep --save

然后将其添加到代码中的 require 部分: const sleep = require('sleep');

然后在你的 for 循环中: sleep.sleep(5); // sleep for 5 seconds sleep.msleep(5); // sleep for 5 milliseconds

【讨论】:

  • 哇,这很容易,谢谢。 npm 会针对模块中已弃用的名为 ForceSet 的内容发出警告。不知道它是否相关。
  • @Mulperi - 简单的延迟并不是实现每秒 20 个请求的最佳方式。要以正确的方式做到这一点,您需要跟踪在最后一秒内发送了多少请求,并在达到 20 时停止发送,设置允许发送新请求的计时器,等等...这样做可以通过过度补偿使你低于限制,但这并不是保持低于限制的最快方法。
  • 另外,如果这是npmjs.com/package/sleep,那么它会阻塞整个node.js 事件循环,这真的很糟糕。您无法处理睡眠时可能到达的任何其他请求。它本质上“挂起”整个服务器的睡眠时间。主要用于调试。
  • @jfriend00:有什么建议可以跟踪时间吗?使用节点计时器或类似的东西?
  • @Mulperi - 你看过the post I linked in a comment to your question吗?这显示了如何在该代码中计算请求/秒。我在一个多小时前发布了该参考资料,而您对此一无所知。该特定代码可能会解决您的问题,并且肯定会说明如何进行此类工作。请阅读该答案并研究该代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 2017-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多