How does the delay parameter of setTimout() work within a loop?

I have the following code that involves an IIFE (immediately invoking function expression) within a for loop. The IIFE function is clearly getting the right parameter as the printout is as expected. But I don't understand what the interval is doing. As far as I can tell the interval for the 1st iteration should be 1 sec, then 2 sec for the 2nd iteration, etc. etc.

for (var i = 1; i <= 5; i++) {

    (function(i){
        setTimeout(function timer(){
            console.log(i);
        }, i*1000);
    })(i);

}

I see i printed out as 1..5 in 1 second intervals. This is confusing for me, as I was expecting the interval to increase with each iteration.

With the following code:

for (var i = 1; i <= 5; i++) {

    (function(i){
        setTimeout(function timer(){
            console.log(i);
        }, 1000);
    })(i);

}

I see all the values for i printed at once after a 1 second interval.

What is happening within the setTimeout function that is making it work in the way observed?


The for loop runs to completion. It doesn't wait for the setTimeout() call to fire. So, when the for loop is running, it schedules setTimeout() calls for 1000, 2000, 3000, 4000, 5000 ms from now. Thus, you see them all fire one second apart.

What is happening within the setTimeout function that is making it work in the way observed?

setTimeout() is a non-blocking, asynchronous operation. It is scheduled to run in the future, but the other code around it continues to run. Then, sometime in the future the timer fires and the callback is called.

So, your code is essentially this:

setTimeout(fn, 1000);
setTimeout(fn, 2000);
setTimeout(fn, 3000);
setTimeout(fn, 4000);
setTimeout(fn, 5000);

It runs all the setTimeout() calls one after the other in a non-blocking fashion. Each setTimeout() function call just registers a callback and a time with the underlying system and then the next line of code continues to execute. Then, sometime later when the right amount of time has passed, the callback gets called. So, hopefully you can see that all the timers are all scheduled to measure their time starting from now. Thus, you see them fire each 1 second apart.

If you want an analogy for an asynchronous operation, imagine you walk around your house and you set five alarm clocks to start ringing at a time in the future. You set one to ring an hour from now, one for two hours from now, one for three hours from now, etc... Then, you go about your other business, make lunch, clean the kitchen, mow the grass, etc... and one hour from when you set all the clocks, the first alarm starts ringing. One hour after that, the next one starting ringing, etc... You get to keep doing things before and after they ring. You don't have to sit and wait for a clock to ring before doing anything else. That's what Javascript asynchronous timer operations are like. You set them and then keep running other code and they fire at their scheduled time in the future.


Try this :

function recursiveTimeout(i) {
        setTimeout(function timer(){    
          console.log(i);
          if(i<5) {
            recursiveTimeout(i+1);
          }
        }, 1000 * i);
}
recursiveTimeout(1);

That way the next setTimeout is depending of the end of parent timer.

链接地址: http://www.djcxy.com/p/51602.html

上一篇: JavaScript关闭优势?

下一篇: setTimout()的延迟参数如何在循环中工作?