JavaScript - setTimeout

javascript

https://coderwall.com/p/_ppzrw/be-careful-with-settimeout-in-loops
http://brackets.clementng.me/post/24150213014/example-of-a-javascript-closure-settimeout-inside
http://borgs.cybrilla.com/tils/javascript-for-loop-with-delay-in-each-iteration-using-iife/
https://javascript.info/settimeout-setinterval
https://scottiestech.info/2014/07/01/javascript-fun-looping-with-a-delay/
https://forum.freecodecamp.org/t/settimeout-loop/39556
https://dzone.com/articles/why-does-javascript-loop-only-use-last-value

How can we sleep using setTimeout?

const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));

The above code is a function which takes one parameter named time, and returns a promise that is resolved after the specified amount of time. This function is stored inside a variable named sleep. We can use this function:

sleep(500).then(() => {
    // Do something after the sleep!
})

This is not that much different from the traditional way of using setTimeout:

setTimeout(function(){ ... }, timeInMilliseconds);

How can we create a loop using setTimeout?

Imagine a situation when we have to do a certain amount of work preferably in the front-end. If the amount of work is simple or small, we can use the traditional for or while loop. However if the amount of work is large, we should consider using the back-end to do the work and return the result to the front-end, because if we try to do this on the front-end using the traditional for or while loop approach, the browser may display a message such as "A script on this page is causing Internet Explorer to run slowly", or your application UI may feel sluggish.

If the work must be done on the front-end based on the nature of the work (for example, the loop inside the Selenium Core (version 1) framework that is used to drive the browser), we can create a loop using setTimeout:

function doWork() {
    if (thereIsWorkToBeDone) {
        // do some work
        setTimeout(doWork,0);
    }
}

In the above code, the "do some work" part is just a small chunk of the total amount of work that we have to do. The above code show the basic of using setTimeout to form a loop. The second parameter to setTimeout can be any positive integer representing the number of millisecond between each time that the function doWork is invoked. Now, lets say that we move the "do some work" part into a function named doActualWork, and it actually returns a promise, we can then modify our doWork function:

function doWork() {
    if (thereIsWorkToBeDone) {
        let p = doActualWork();
        p.then(function() {
            if (thereIsWorkToBeDone) {
                setTimeout(doWork,0);
            }
        });
    }
}

With the above modification, our doWork function is not invoked until the first chunk of work is completed. Now, let assume that the caller of our doWork function need to be notified when doWork is done, we can modify the caller to invoke doWork:

new Promise(function(resolve,reject) {
    doWork(resolve, reject);
}).then(function() {
    ...
}).catch(function() {
    ...
});

And we need to modify the doWork function:

function doWork(resolve,reject) {
    if (thereIsWorkToBeDone) {
        let p = doActualWork();
        p.then(function() {
            if (thereIsWorkToBeDone) {
                setTimeout(function(){
                    doWork(resolve,reject);
                },0);
            } else {
                resolve();
            }
        }).catch(function(){
            reject();
        });
    }
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License