首页 > 解决方案 > 如何使异步任务同步重复

问题描述

我有一个要运行的 Node.js 后台任务,它将进行多个 API 调用。我的最终目标是有一个主要的异步循环,当完成时,它会再次启动。每个 API 调用都是异步的,但是我想按顺序执行它们。

我考虑过执行以下操作:

  1. 添加await到每个函数调用
  2. 制作循环async
  3. 在异步函数完成后调用循环
  4. loop在程序开始时进行1 次主调用以对其进行初始化

例子:

var loop = async function() {
   await asyncFunctionOne();
   await asyncFunctionTwo();
   await asyncFunctionThree();

   loop();
}

loop();

对于上下文,我在 Node.js Web 应用程序上运行这个后台任务,所以这个循环应该在一边异步运行。

我想知道上面的例子是否是一种有效的方法——如果我让这个无限期地运行,这会占用很多内存吗?我不完全确定堆栈溢出是如何工作的,但这会导致堆栈溢出或任何其他类型的问题吗?如果有更好的方法来编写此代码,请告诉我。谢谢!

标签: node.jsasynchronous

解决方案


您显示的内容会运行一次循环:

var loop = async function() {
   await asyncFunctionOne();
   await asyncFunctionTwo();
   await asyncFunctionThree();
}

loop();

如果你想一遍又一遍地运行它,你可以让它在完成后调用自己:

var loop = async function() {
   await asyncFunctionOne();
   await asyncFunctionTwo();
   await asyncFunctionThree();
   // after short delay, call itself again
   // delay can be removed if you really want to hammer external resources
   //     as much as possible, but usually, you don't want to put that much
   //     load on external resources
   setTimeout(loop, 1000);
}

loop();

这在 node.js 中是一件非常好的事情。没有堆栈积累,没有内存积累(假设你的函数本身没有做一些故意积累内存的事情)。

我想知道上面的例子是否是一种有效的方法

是的,这是一种有效的方法。

对于上下文,我在 Node.js Web 应用程序上运行这个后台任务,所以这个循环应该在一边异步运行。

请记住,node.js 运行您的 Javsacript 单线程,因此当其中一个函数需要运行一些 Javascript 时,这发生在前台,而不是后台。但只要这些函数中没有 CPU 密集型,而且它们大多只是异步 I/O 调用,它就不会特别干扰您的 node.js 服务器可能想要做的其他事情。对于对主 node.js 事件循环完全没有影响的完全后台操作,您可能希望启动另一个 node.js child_process 来运行此循环或使用更新的Worker thread API

如果我无限期地保持这个运行,这会占用很多内存吗?

如果您的函数本身没有故意将内存累积到一些持久性更高范围的变量中,那么这不应该是累积内存。没有堆栈堆积,垃圾收集将清除任何临时内存使用。内存使用应该在几次迭代后上升到一个稳定的状态值,之后不会持续上升。

但这会导致堆栈溢出或任何其他类型的问题吗?

这里没有堆栈溢出。每次迭代loop()在下一次运行之前完成。

如果有更好的方法来编写此代码,请告诉我。

要提出替代建议,我们需要确切地知道您正在解决的现实世界问题是什么,并查看实际代码。就理论上的解决方案而言,这很好。优化解决方案需要查看实际问题和实际代码。很难优化一个理论问题。

例如,这听起来像是您正在轮询一些外部资源以进行更改或更新,这通常是低效的。是否有一种更有效的方式来做任何你想做的事情,这完全取决于你轮询的特定资源是如何工作的,当你获得更新时你对数据做了什么,以及这些更新的频率是多少在您的实际应用程序/客户端的上下文中需要。


推荐阅读