如何在没有递归的情况下在 JavaScript 中编写非阻塞、延迟的 for 循环?

How to write a non-blocking, delayed for loop in JavaScript without recursion?

提问人:Oliver Hihn 提问时间:10/19/2023 更新时间:10/19/2023 访问量:62

问:

我想要一个 for 循环,每 X 毫秒执行一次代码。它应该是非递归的,以避免在多次迭代后出现堆栈溢出。此外,它应该是非阻塞的,并且其性能应该不错。

我用一个承诺尝试了一下:

(async () => {
  for (var i = 0; i <= 30; i++) {
    await new Promise(async (res, rej) => {
      setTimeout(() => {
        console.log("run number", i);
        res();
      }, 100);
    });
  }
})();

但是第一次执行是在传递给 setTimeout 的持续时间之后,而不是像在真正的 for 循环中那样执行一次。

JavaScript for 循环 异步 承诺

评论

4赞 Reyno 10/19/2023
将您的逻辑移到 ?await
1赞 jfriend00 10/20/2023
为什么行不通?setInterval()

答:

-1赞 Pointy 10/19/2023 #1

您必须将执行您想做的任何工作的函数从循环中拉出。然后,您可以在第一次迭代循环开始之前调用它,然后在之后的定时间隔之后调用它。

(async () => {
  function doWork(iteration, finish) {
    console.log(`run number ${iteration}`);
    finish();
  }

  doWork(0, _ => _);
  for (var i = 1; i <= 30; i++) {
    await new Promise(async (res, rej) => {
      setTimeout(() => {
        doWork(i, res);
      }, 100);
    });
  }
})();

评论

0赞 Pointy 10/19/2023
Promise 初始值设定项函数实际上不一定是 。async
0赞 Bergi 10/19/2023
...并且您永远不应该在 promise 代码中通过回调进行工作,因为 无法处理异常setTimeoutsetTimeout
1赞 Pointy 10/20/2023
@Bergi哦,是的,好点,我坚持原来的模式。老实说,OP 的解决方案可能更好:)
2赞 Oliver Hihn 10/19/2023 #2

我想我明白了。这是我的解决方案:

(async() => {
  for (let i = 0; i <= 30; i++) {
    console.log("run number", i);
    await new Promise((resolve) => setTimeout(resolve, 100));
  }
})();

评论

1赞 Pointy 10/19/2023
是的,这也很好。