使用 setInterval() 的无限异步循环 [重复]

Posted

技术标签:

【中文标题】使用 setInterval() 的无限异步循环 [重复]【英文标题】:Infinite async loops using setInterval() [duplicate] 【发布时间】:2019-07-05 05:34:16 【问题描述】:

我有 nodejs 应用程序,它需要一些调用异步函数的无限循环。我正在考虑实施以下措施:

async function execute1() 
   ...do some async work...


async function execute2() 
   ...do some async work...


setInterval(execute1, 500)
setInterval(execute2, 500)

我担心的是,如果异步函数需要很长时间才能完成,打开的引用会堆积起来,这可能会导致内存崩溃。

    setInterval 是适合这项工作的工具吗?有没有更合适的工具? 如果之前的运行没有返回,确保 execute() 函数不会启动的最优雅的方法是什么?

【问题讨论】:

你需要await那些异步事件 你可以在通话中setTimerOut(),一旦完成,它会调用自己。 “我的 nodejs 应用需要几个无限循环” 为什么需要无限循环?为什么需要setInterval() 【参考方案1】:

setTimeout 在这种情况下可能会更好。

async function execute1(delay) 
   // await ...
   setTimeout(() => execute1(delay), delay)

execute1(500)

【讨论】:

@messerbill — 不,不会。答案完全无法解释这种方法是如何工作的,但它会反复运行。 它会执行一次,然后调用setTimeout再次执行,然后再次&再次,... omg...我错过了自己的电话,只看了setTimeout....nvm【参考方案2】:

您可以使用简单的标志来指示之前的功能是否仍在运行

let isRunning = false;

async function execute1() 
   if (isRunning) return;
   isRunning = true

   ...do some async work...

   // make sure to call this whether it succeeds or fails, maybe in a finally block
   isRunning = false


setInterval(execute1, 500)

【讨论】:

公平,但我认为 setTimeout 可能是这个更简单的解决方案。 对某些人来说可能并不明显,但如果...do some async work... 不包含任何await 语句,if (isRunning) 将永远不会在isRunning === true 时执行。【参考方案3】:

setInterval 不是正确的工具,因为它不知道 Promise 并且无法保持正确的控制流。

可以是async函数无限循环:

async function execute1() 
  while (true) 
    await new Promise(resolve => setTimeout(resolve, 500));
    // ...do some async work...  
  


execute1();

【讨论】:

如何将break 跳出while 循环? @guest271314 使用条件而不是true FWIW 一种模式,用于实现打破循环let done; while ((done = await new Promise(resolve => ..).then(() => return !done)))Why does assignment using await within while expression not retain assigned value? 的条件。以及基于前一种模式Run multiple recursive Promises and break when requested 的详细方法【参考方案4】:

您可以创建一个运行execute1() 的函数,然后等待它完成,然后使用setTimeout() 自行运行。

function randomSleep() 
  return new Promise(resolve => setTimeout(resolve, Math.random() * 3000));


let done = 0;

async function execute1() 
   console.log('Execute 1 started.')
   await randomSleep()
   return 'done'


const run = () => 
  execute1().then(result => 
    console.log('Execute 1 ended')
    done++
    console.log(`Done $done times.`)
    console.log(`Now waiting for 2 seconds`)
    setTimeout(() => 
      run()
    , 2000)
  )


run()

【讨论】:

在 node.js 中测试了这个。它不应该与我们的 randomSleep 部分一起使用吗?删除该部分时,这不会等待 execute1() 完成。

以上是关于使用 setInterval() 的无限异步循环 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Promises 进行异步无限循环

为啥这个异步函数无限循环?

setinterval是异步还是同步

为啥计算内部的异步会产生无限循环(vue)?

异步、等待和无限循环

Angular 2 - 异步管道中的无限循环