Four solutions for using setTimeout in JS for loop

Four solutions for using setTimeout in JS for loop

Overview

Let's first take a brief look at the operating mechanism of the setTimeout delay. setTimeout will first put the callback function in the waiting queue, and after other main programs in the waiting area are executed, the callback function will be executed in chronological order. It's essentially a question of scope.

Therefore, if this is done, the desired output 1.2.3.4.5 will not be obtained, but 5 consecutive 6s will be output.

for (var i=1; i<=5; i++) {
    setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
}

This is because setTimeout is executed asynchronously. Each time the for loop is executed, setTimeout is executed once, but the function inside is not executed. Instead, it is placed in the task queue and waits for execution. Only when the tasks on the main line are completed will the tasks in the task queue be executed. That is to say, it will wait until the for loop is completely finished before executing the fun function. However, when the for loop ends, the value of i has become 6. Therefore, although the timer runs for 5 seconds, the content on the console is still 6.

(Note: The for loop needs to last for a few microseconds or milliseconds from the beginning to the end. When the timer runs out of one second, the for loop has already been completed.)

Let's look at another case:

for (var i=1; i<=5; i++) {
    (function() {
        setTimeout( function timer() {
            console.log( i );
        }, i*1000 );
    })();
}

From the operating mechanism of setTimeout, we can know that all external main programs will be run first. Although a closure is formed in the for loop, fun does not find an actual parameter, so there is no actual difference from the first example, and 5 consecutive 6s are still output.

Solution 1: Closures

Using closures is a classic approach:

for (var i=1; i<=5; i++) {
    (function(j) {
        setTimeout( function timer() {
            console.log( j );
        }, j*1000 );
    })(i);
}

We can find that the expected result is consistent with the output of 1 to 5 in sequence. This is because the actual parameters have a strong dependence on i inside the timer.

Through the closure, the variable i resides in the memory. When j is output, the variable value i of the external function is referenced. The value of i is based on the loop, and the output inside has been determined when setTimeout is executed.

Solution 2: Split the structure

We can also put the definition and call of setTimeout into different parts:

function timer(i) {
    setTimeout( console.log( i ), i*1000 );
}
for (var i=1; i<=5;i++) {
    timer(i);
}

The output on the console is still 1 to 5 in sequence.

Solution 3: let

Here is another way to solve this problem using es6's let:

for (let i=1; i<=5; i++) {
    setTimeout( function timer() {
        console.log( i );
     }, i*1000 );
}

Compared with the first example, this example only changes var to let, but the console outputs 1 to 5 in sequence.

Because the let at the head of the for loop not only binds i to the for loop, it actually rebinds it to each iteration of the loop body, ensuring that the value at the end of the previous iteration is reassigned. The function() in setTimeout belongs to a new scope. Variables defined by var cannot be passed into the execution scope of this function. By using let to declare block variables, they can act on this block, so function can use the variable i. The parameter scope of this anonymous function is different from the scope of the for parameter, and this is achieved by taking advantage of this. The scope of this anonymous function is somewhat similar to the attributes of a class and can be used by inner methods.

Solution 4: setTimeout third parameter

for (let i=1; i<=5; i++) {
    setTimeout( function timer() {
        console.log( i );
     }, i*1000, i );
}

Since the parameters passed in each time are values ​​taken from the for loop, 1 to 5 will be output in sequence.

The above are the details of the four solutions for using setTimeout in JS for loops. For more information about using setTimeout in JS, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • JavaScript uses setTimeout to achieve countdown effect
  • What are the basic uses of JavaScript setTimeout()
  • JavaScript setInterval() vs setTimeout() Timers
  • Simply use settimeout to see the operating mechanism of javascript
  • How to understand the JS operation mechanism through setTimeout
  • Look at the js function execution process from setTimeout
  • js learn to use setTimeout to implement round-robin animation
  • Analysis of JavaScript timer usage [setTimeout and clearTimeout]
  • Detailed explanation of the this pointing problem of timer setInterval and setTImeout in JS
  • Things about setTimeout in JavaScript

<<:  Detailed explanation of the use of shared memory in nginx

>>:  Detailed installation and use of RocketMQ in Docker

Recommend

Detailed installation process of MySQL5.6.40 under CentOS7 64

MySQL5.6.40 installation process under CentOS7 64...

How to upgrade MySQL 5.6 to 5.7 under Windows

Written in front There are two ways to upgrade My...

Introduction to the process of installing MySQL 8.0 in Linux environment

Table of contents Preface 1. Linux changes the yu...

Tutorial on installing lamp-php7.0 in Centos7.4 environment

This article describes how to install lamp-php7.0...

How to dynamically modify the replication filter in mysql

MySQL dynamically modify replication filters Let ...

Solution to the automatic stop of MySQL service

This article mainly introduces the solution to th...

JS implements the rock-paper-scissors game

This article example shares the specific code of ...

Ant designing vue table to achieve a complete example of scalable columns

Perfect solution to the scalable column problem o...

HTML embed tag usage and attributes detailed explanation

1. Basic grammar Copy code The code is as follows...

Correct modification steps for Docker's default network segment

background A colleague is working on his security...