我想在while循环中添加一个delay/sleep:

我是这样试的:

alert('hi');

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

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

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


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

你也可以通过使用一个自调用函数,将迭代次数作为参数传递给它:

(函数myLoop(i) { setTimeout(函数(){ console.log('你好');//你的代码 if(——i) myLoop(i);//减少i,如果i > 0再次调用myLoop }, 3000) }) (10);//传递迭代次数作为参数


试试这样做:

var i = 0, howManyTimes = 10; 函数f() { console.log(“嗨”); 我+ +; if (i < howManyTimes) { setTimeout (3000); } } f ();


另一种方法是将超时时间相乘,但请注意,这与睡眠不同。循环之后的代码将立即执行,只有回调函数的执行被延迟。

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

第一个超时设置为3000 * 1,第二个超时设置为3000 * 2,依此类推。


我认为你需要这样的东西:

var TimedQueue = function(defaultDelay){
    this.queue = [];
    this.index = 0;
    this.defaultDelay = defaultDelay || 3000;
};

TimedQueue.prototype = {
    add: function(fn, delay){
        this.queue.push({
            fn: fn,
            delay: delay
        });
    },
    run: function(index){
        (index || index === 0) && (this.index = index);
        this.next();
    },
    next: function(){
        var self = this
        , i = this.index++
        , at = this.queue[i]
        , next = this.queue[this.index]
        if(!at) return;
        at.fn();
        next && setTimeout(function(){
            self.next();
        }, next.delay||this.defaultDelay);
    },
    reset: function(){
        this.index = 0;
    }
}

测试代码:

var now = +new Date();

var x = new TimedQueue(2000);

x.add(function(){
    console.log('hey');
    console.log(+new Date() - now);
});
x.add(function(){
    console.log('ho');
    console.log(+new Date() - now);
}, 3000);
x.add(function(){
    console.log('bye');
    console.log(+new Date() - now);
});

x.run();

注意:使用警报暂停javascript执行,直到你关闭警报。 它的代码可能比您要求的要多,但这是一个健壮的可重用解决方案。


我可能会使用setInterval,像这样:

var period = 1000; // ms
var endTime = 10000;  // ms
var counter = 0;
var sleepyAlert = setInterval(function(){
    alert('Hello');
    if(counter === endTime){
       clearInterval(sleepyAlert);
    }
    counter += period;
}, period);

/* 
  Use Recursive  and setTimeout 
  call below function will run loop loopFunctionNeedCheck until 
  conditionCheckAfterRunFn = true, if conditionCheckAfterRunFn == false : delay 
  reRunAfterMs miliseconds and continue loop
  tested code, thanks
*/

function functionRepeatUntilConditionTrue(reRunAfterMs, conditionCheckAfterRunFn,
 loopFunctionNeedCheck) {
    loopFunctionNeedCheck();
    var result = conditionCheckAfterRunFn();
    //check after run
    if (!result) {
        setTimeout(function () {
            functionRepeatUntilConditionTrue(reRunAfterMs, conditionCheckAfterRunFn, loopFunctionNeedCheck)
        }, reRunAfterMs);
    }
    else  console.log("completed, thanks");    
            //if you need call a function after completed add code call callback in here
}

//passing-parameters-to-a-callback-function
// From Prototype.js 
if (!Function.prototype.bind) { // check if native implementation available
    Function.prototype.bind = function () {
        var fn = this, args = Array.prototype.slice.call(arguments),
            object = args.shift();
        return function () {
            return fn.apply(object,
              args.concat(Array.prototype.slice.call(arguments)));
        };
    };
}

//test code: 
var result = 0; 
console.log("---> init result is " + result);
var functionNeedRun = function (step) {           
   result+=step;    
       console.log("current result is " + result);  
}
var checkResultFunction = function () {
    return result==100;
}  

//call this function will run loop functionNeedRun and delay 500 miliseconds until result=100    
functionRepeatUntilConditionTrue(500, checkResultFunction , functionNeedRun.bind(null, 5));

//result log from console:
/*
---> init result is 0
current result is 5
undefined
current result is 10
current result is 15
current result is 20
current result is 25
current result is 30
current result is 35
current result is 40
current result is 45
current result is 50
current result is 55
current result is 60
current result is 65
current result is 70
current result is 75
current result is 80
current result is 85
current result is 90
current result is 95
current result is 100
completed, thanks
*/

我用蓝鸟的承诺。延时和递归。

函数 myLoop(i) { 返回承诺延迟(1000) .then(function() { 如果 (i > 0) { 警报(“你好”); 返回 myLoop(i -= 1); } }); } 我的循环(3); <script src=“//cdnjs.cloudflare.com/ajax/libs/bluebird/2.9.4/bluebird.min.js”></script>


下面是我用来循环数组的函数:

function loopOnArrayWithDelay(theArray, delayAmount, i, theFunction, onComplete){

    if (i < theArray.length && typeof delayAmount == 'number'){

        console.log("i "+i);

        theFunction(theArray[i], i);

        setTimeout(function(){

            loopOnArrayWithDelay(theArray, delayAmount, (i+1), theFunction, onComplete)}, delayAmount);
    }else{

        onComplete(i);
    }
}

你可以这样使用它:

loopOnArrayWithDelay(YourArray, 1000, 0, function(e, i){
    //Do something with item
}, function(i){
    //Do something once loop has completed
}

在ES6 (ECMAScript 2015)中,您可以使用生成器和间隔迭代延迟。

生成器(generator)是ECMAScript 6的一个新特性,是可以被替换的函数 顿了顿,接着说。调用genFunc不会执行它。相反,它 返回一个所谓的生成器对象,让我们控制genFunc的 执行。genFunc()最初是挂起在它的开始 的身体。方法genObj.next()继续执行genFunc, 直到下一次丰收。 (探索ES6)

代码示例: Let arr = [1,2,3, 'b']; let genObj = genFunc(); let val = genObj.next(); console.log (val.value); let interval = setInterval(() => { val = genObj.next(); If (val.done) { clearInterval(间隔); }其他{ console.log (val.value); } }, 1000); 函数* genFunc() { For (let item of arr) { 收益项; } }

所以如果你正在使用ES6,这是实现延迟循环的最优雅的方式(在我看来)。


我只是想在这里发表我的意见。此函数运行具有延迟的迭代循环。请看这个jsfiddle。函数如下:

function timeout(range, time, callback){
    var i = range[0];                
    callback(i);
    Loop();
    function Loop(){
        setTimeout(function(){
            i++;
            if (i<range[1]){
                callback(i);
                Loop();
            }
        }, time*1000)
    } 
}

例如:

//This function prints the loop number every second
timeout([0, 5], 1, function(i){
    console.log(i);
});

相当于:

//This function prints the loop number instantly
for (var i = 0; i<5; i++){
    console.log(i);
}

var startIndex = 0; Var数据= [1,2,3]; Var超时= 1000; 函数functionToRun(i, length) { 警报(数据[我]); } (函数forWithDelay(i, length, fn, delay) { setTimeout(函数(){ fn(我、长度); 我+ +; If (i < length) { forWithDelay(i, length, fn, delay); } },延迟); }) (startIndex数据。length, functionToRun, timeout);

Daniel Vassallo回答的修改版本,将变量提取为参数,使函数更具可重用性:

首先让我们定义一些基本变量:

var startIndex = 0;
var data = [1, 2, 3];
var timeout = 3000;

接下来,您应该定义要运行的函数。这将传递i,循环的当前索引和循环的长度,以防你需要它:

function functionToRun(i, length) {
    alert(data[i]);
}

Self-executing版本

(function forWithDelay(i, length, fn, delay) {
   setTimeout(function () {
      fn(i, length);
      i++;
      if (i < length) {
         forWithDelay(i, length, fn, delay); 
      }
  }, delay);
})(startIndex, data.length, functionToRun, timeout);

功能版

function forWithDelay(i, length, fn, delay) {
   setTimeout(function () {
      fn(i, length);
      i++;
      if (i < length) {
         forWithDelay(i, length, fn, delay); 
      }
  }, delay);
}

forWithDelay(startIndex, data.length, functionToRun, timeout); // Lets run it

如果使用ES6,你可以使用for循环来实现:

For(令I = 1;I < 10;我+ +){ setTimeout(函数定时器(){ console.log(“hello world”); }, I * 3000); }

它为每次迭代声明i,这意味着超时是+ 1000之前的超时。这样,传递给setTimeout的就是我们想要的。


这个脚本适用于大多数情况

function timer(start) {
    setTimeout(function () { //The timer
        alert('hello');
    }, start*3000); //needs the "start*" or else all the timers will run at 3000ms
}

for(var start = 1; start < 10; start++) {
    timer(start);
}

你可以使用RxJS的间隔操作符。Interval每x秒发出一个整数,take指定它发出这些数字的次数。

Rx。可观测的 .interval (1000) (10), .subscribe((x) => console.log(x)) < script src = " https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.lite.min.js " > < /脚本>


这是可行的

for (var i = 0; i < 10; i++) {
  (function(i) {
    setTimeout(function() { console.log(i); }, 100 * i);
  })(i);
}

试试这把小提琴:https://jsfiddle.net/wgdx8zqq/


因为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();

当引擎到达await部分时,它设置一个超时并停止async函数的执行。然后,当超时完成时,继续执行。这是非常有用的,因为你可以延迟(1)嵌套循环,(2)有条件的,(3)嵌套函数:

异步函数任务(i) {// 3 等待计时器(1000); console.log('任务${i}完成! '); } 异步函数main() { 对于(设I = 0;I < 100;I += 10) { For(令j = 0;J < 10;j++) {// 1 如果(j % 2) {// 2 等待任务(i + j); } } } } main (); 函数定时器(ms){返回新的承诺(res => setTimeout(res, ms));}

MDN参考资料

虽然ES7现在被NodeJS和现代浏览器支持,但你可能想用BabelJS编译它,这样它就可以在任何地方运行。


下面是我如何创建一个无限循环的延迟,在特定条件下中断:

  // Now continuously check the app status until it's completed, 
  // failed or times out. The isFinished() will throw exception if
  // there is a failure.
  while (true) {
    let status = await this.api.getStatus(appId);
    if (isFinished(status)) {
      break;
    } else {
      // Delay before running the next loop iteration:
      await new Promise(resolve => setTimeout(resolve, 3000));
    }
  }

这里的关键是创建一个通过超时解析的新Promise,并等待它的解析。

显然你需要async/await支持。工作在Node 8。


对于常用的“忘记正常循环”和使用这个组合的“setInterval”包括“setTimeOut”:像这样(从我的实际任务)。

        function iAsk(lvl){
            var i=0;
            var intr =setInterval(function(){ // start the loop 
                i++; // increment it
                if(i>lvl){ // check if the end round reached.
                    clearInterval(intr);
                    return;
                }
                setTimeout(function(){
                    $(".imag").prop("src",pPng); // do first bla bla bla after 50 millisecond
                },50);
                setTimeout(function(){
                     // do another bla bla bla after 100 millisecond.
                    seq[i-1]=(Math.ceil(Math.random()*4)).toString();
                    $("#hh").after('<br>'+i + ' : rand= '+(Math.ceil(Math.random()*4)).toString()+' > '+seq[i-1]);
                    $("#d"+seq[i-1]).prop("src",pGif);
                    var d =document.getElementById('aud');
                    d.play();                   
                },100);
                setTimeout(function(){
                    // keep adding bla bla bla till you done :)
                    $("#d"+seq[i-1]).prop("src",pPng);
                },900);
            },1000); // loop waiting time must be >= 900 (biggest timeOut for inside actions)
        }

PS:理解(setTimeOut)的真实行为:它们都将在同一时间开始“三个bla bla bla将在同一时刻开始倒数”,因此设置不同的超时来安排执行。

PS 2:计时循环的例子,但对于一个反应循环,你可以使用事件,承诺async await ..


<!DOCTYPE html > < html > 身体< > <按钮onclick = " myFunction ()”> > < /按钮试试 < p id = "演示" > < / p > <脚本> 函数myFunction() { (var = 0;我< 5;我+ +){ Var sno = i+1; (函数myLoop (i) { setTimeout(函数(){ 警报(我);//在这里完成你的功能 }, 1000 *我); }) (sno); } } > < /脚本 < /身体> < / html >


试试这个…

var icount=0;
for (let i in items) {
   icount=icount+1000;
   new beginCount(items[i],icount);
}

function beginCount(item,icount){
  setTimeout(function () {

   new actualFunction(item,icount);

 }, icount);
}

function actualFunction(item,icount){
  //...runs ever 1 second
 console.log(icount);
}

简单实现了在循环运行期间每两秒显示一段文本。

for (var i = 0; i < foo.length; i++) {
   setInterval(function(){ 
     console.log("I will appear every 2 seconds"); 
   }, 2000);
  break;
};

据我所知,setTimeout函数是异步调用的。你能做的是将整个循环包装在一个异步函数中,并等待一个包含setTimeout的Promise,如下所示:

var looper = async function () {
  for (var start = 1; start < 10; start++) {
    await new Promise(function (resolve, reject) {
      setTimeout(function () {
        console.log("iteration: " + start.toString());
        resolve(true);
      }, 1000);
    });
  }
  return true;
}

然后像这样调用运行它:

looper().then(function(){
  console.log("DONE!")
});

请花些时间好好理解异步编程。


你这样做:

console.log(“嗨”) Let start = 1 setTimeout(函数(){ let interval = setInterval(函数(){ if(start == 10) clearInterval(interval) 开始+ + console.log(“你好”) }, 3000) }, 3000) < script src = " https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js " > < /脚本>


   let counter =1;
   for(let item in items) {
        counter++;
        setTimeout(()=>{
          //your code
        },counter*5000); //5Sec delay between each iteration
    }

在ES6中,你可以这样做:

对于(设I = 0;I <= 10;我+ +){ setTimeout(函数(){ console.log(我); },我* 3000) }

在ES5中,你可以这样做:

For (var I = 0;I <= 10;我+ +){ (函数(i) { setTimeout(函数(){ console.log(我); },我* 3000) }) (); }

原因是,let允许您声明限制在块语句或使用它的表达式范围内的变量,而不像var关键字那样全局定义变量,或局部定义整个函数,而不考虑块范围。


试试这个

 var arr = ['A','B','C'];
 (function customLoop (arr, i) {
    setTimeout(function () {
    // Do here what you want to do.......
    console.log(arr[i]);
    if (--i) {                
      customLoop(arr, i); 
    }
  }, 2000);
})(arr, arr.length);

结果

A // after 2s
B // after 2s
C // after 2s

除了10年前接受的答案之外,使用更现代的Javascript,可以使用async/await/Promise()或生成器函数来实现正确的行为。(其他答案中建议的错误行为是设置一系列3秒警报,而不管“接受”警报()-或完成手头的任务)

使用异步/等待/承诺(): alert('嗨'); (async () => { For (let start = 1;起始值< 10;开始+ +){ 等待新的承诺(resolve => setTimeout(() => { alert('你好'); 解决(); }, 3000)); } }) ();

使用生成器函数:

警报(“嗨”); 让函子; (func = (function*() { for(let start = 1, start < 10, start++) { yield setTimeout(() => { 警报(“你好”); func.next(); }, 3000); } })()).next();


您可以创建一个承诺setTimeout的睡眠函数。这使您可以使用async/await来编写代码,而无需回调和熟悉的for循环控制流。

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); (async () => { 对于(设I = 0;I < 10;我+ +){ console.log(我); 等待睡眠(1000); } console.log(“完成”); }) ();

在Node中,你可以使用计时器/承诺来避免承诺步骤(如果旧版本的Node不支持该功能,上面的代码也可以工作):

const {setTimeout: sleep} = require("timers/promises");

// same code as above

无论如何,由于JS是单线程的,超时是异步的是一件好事。如果不这样做,浏览器就没有机会重新绘制UI,从而导致用户的界面冻结。


在我看来,在循环中添加延迟的最简单和最优雅的方法是这样的:

names = ['John', 'Ana', 'Mary'];

names.forEach((name, i) => {
 setTimeout(() => {
  console.log(name);
 }, i * 1000);  // one sec interval
});

一个无功能的解决方案

我有点晚了,但有一个不使用任何函数的解决方案:

alert('hi');

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

const autoPlayer = (arr = [1, 2, 3, 4, 5]) => {
  // Base case:
  if (arr.length < 1) return

  // Remove the first element from the array.
  const item = arr.shift()

  // Set timout 
  setTimeout(() => {
    console.log('Hello, world!', item)  // Visualisation.
    autoPlayer() // Call function again.
  }, 1000) // Iterate every second.
}

Hey, I know this post is very old, but this code "loops" and adds a delay to it using a recursive method. I don't think you can 'actually' delay a loop itself from iterating based on reading various comments from other people. Maybe this can help someone out! Basically the function accepts an array (in this example). On each iteration the setTimeout Javascript method is called. The function calls itself again indefinitely when the timer of the setTimeout function expires, but on each call the array becomes smaller until it reaches the base-case. I hope this can help anyone else out.


非常简单的单行解决方案,具有实际的异步等待延迟(没有排队setTimeout):

下面的(自动执行匿名)函数在循环之间创建一个实际的延迟,而不是具有不同超时的多个settimeout,这可能会弄乱内存。

在100个循环中的每一个循环中,它都等待一个新的承诺来解决。 这只发生在setTimeout '允许'它在90ms后。在此之前,代码将被async-await / pending Promise阻塞。

(async () => { For(令i=0;我< 100;我+ +){ 等待新的承诺((resolve) => {setTimeout(() =>{文档。我写(“${}”);解决(true)}, 90)}); } })()