如何在 JavaScript 循环中添加延迟?

2022-08-29 23:12:06

我想在循环中添加延迟/睡眠:while

我试过这样:

alert('hi');

for(var start = 1; start < 10; start++) {
  setTimeout(function () {
    alert('hello');
  }, 3000);
}

只有第一种情况是正确的:显示后,它将等待3秒钟,然后显示,但随后将不断重复。alert('hi')alert('hello')alert('hello')

我想要的是,在显示3秒后,它需要等待3秒第二次,依此类推。alert('hello')alert('hi')alert('hello')


答案 1

setTimeout() 函数是非阻塞函数,将立即返回。因此,您的循环将非常快速地迭代,并且它将快速连续地启动3秒超时触发器。这就是为什么您的第一个警报在3秒后弹出,其余的所有警报都会连续出现,而不会有任何延迟。

您可能希望使用类似如下的内容:

var i = 1;                  //  set your counter to 1

function myLoop() {         //  create a loop function
  setTimeout(function() {   //  call a 3s setTimeout when the loop is called
    console.log('hello');   //  your code here
    i++;                    //  increment the counter
    if (i < 10) {           //  if the counter < 10, call the loop function
      myLoop();             //  ..  again which will trigger another 
    }                       //  ..  setTimeout()
  }, 3000)
}

myLoop();                   //  start the loop

您还可以通过使用自调用函数,将迭代次数作为参数传递来整理它:

(function myLoop(i) {
  setTimeout(function() {
    console.log('hello'); //  your code here                
    if (--i) myLoop(i);   //  decrement i and call myLoop again if i > 0
  }, 3000)
})(10);                   //  pass the number of iterations as an argument

答案 2

由于ES7有更好的方法来等待循环:

// Returns a Promise that resolves after "ms" Milliseconds
const timer = ms => new Promise(res => setTimeout(res, ms))

async function load () { // We need to wrap the loop into an async function for this to work
  for (var i = 0; i < 3; i++) {
    console.log(i);
    await timer(3000); // then the created Promise can be awaited
  }
}

load();

当引擎到达部件时,它会设置超时并暂停异步函数的执行。然后,当超时完成时,执行将在该点继续。这非常有用,因为您可以延迟(1)嵌套循环,(2)有条件地延迟,(3)嵌套函数:await

async function task(i) { // 3
  await timer(1000);
  console.log(`Task ${i} done!`);
}

async function main() {
  for(let i = 0; i < 100; i+= 10) {
    for(let j = 0; j < 10; j++) { // 1
      if(j % 2) { // 2
        await task(i + j);
      }
    }
  }
}
    
main();

function timer(ms) { return new Promise(res => setTimeout(res, ms)); }

MDN上的参考

虽然NodeJS和现代浏览器现在支持ES7,但您可能希望使用BabelJS对其进行转译,以便它可以在任何地方运行。