BDS Software

Javascript Time Delay

Modern Javascript (ES6) provides two built-in time delay functions:

● setTimeout(functionName, n) executes functionName() after n milliseconds.

● setInterval(functionName, n) executes functionName() every n milliseconds.

These built-in functions are very useful for the purposes for which they were designed. But they are asynchronous and don't behave in the synchronous linear fashion which is wanted for other situations. (See Exploring Javascript's setTimeout() Function for a discussion about the use of parentheses in these functions.

For example, Toby Speight and HighCommander4 indicate that in C++ 11, you can use:


#include <chrono>
#include <thread>

std::this_thread::sleep_for(std::chrono::milliseconds(x));

which just pauses the program for x milliseconds - nothing happens during that period, i.e.


doStatementA;
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
doStatementB;
doStatementC;

doStatementA is executed, then nothing happens for 3 seconds, then doStatementB is executed, then doStatementC is executed.

But, in javascript:

doStatementA;
setTimeout(doStatementB, 3000);
doStatementC;

these statements do not proceed in that type of a linear synchronous progression. When setTimeout is encountered, it will execute doStatementB after 3000 milliseconds but, while it's waiting, other work can proceed. Thus doStatementB may be executed after doStatementC. This is often NOT what you want. Try it for yourself:


*****

So, I wrote my own simple time delay function:

function mdjSleepXX(n) {

    var sleepStart;
    var sleepEnd;
    var sleepNow;

    sleepStart = new Date().getTime();
    sleepEnd = sleepStart + n;

    while(true) {
        sleepNow = new Date().getTime();
        if (sleepNow >= sleepEnd) {
            break;
        }
    }
}

Unfortunately, because this is a synchronous (blocking) function, it's not satisfied with just delaying what comes after it; it also delays what comes before it. So, instead of:

didStatementA.
wait.
didStatementB.
didStatementC.

what it actually does is:

wait.
didStatementA.
didStatementB.
didStatementC.

which is also NOT what we want here. Try it for yourself:


*****

I tried various other functions, some of my own design and some which I found on the web, but none of them performed the steps in the order I needed. If you want to check on those various unsuccessful attempts, right-click this page and then click on "View Source" (in Firefox - other browsers similar) to search through my code on your own.

Finally, I came upon a function by gsamaras on the web, which I modified slightly:

function mdjSleep (n) {
    return new Promise((resolve) => setTimeout(resolve, n));
}

which is called like this:

doStatementA();
mdjSleep(n).then(() => { // ** THIS STARTS THE CALL TO THE SLEEP MECHANISM.
    // Do something after the sleep!
    doStatementB();
    doStatementC();
}); // ** THIS ENDS THE CALL TO THE SLEEP MECHANISM.

Although this code is somewhat difficult to follow, it DOES put the time delay just where we want it. Try it for yourself:



                                                                                                                                                                M.D.J. 2018/07/24


----------

References:

Deering, Sam (2012). Delay, sleep, pause, wait etc in JavaScript. https://www.sitepoint.com/delay-sleep-pause-wait/.

gsamaras' StackOverflow response. (2016). What is the Javascript version of sleep(). https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep.

Johnson, M. David. StackOverflow question. (2018). Javascript non-interfering time delay [duplicate]. https://stackoverflow.com/questions/51545818/javascript-non-interfering-time-delay?noredirect=1#comment90059554_51545818.

Speight, Toby and HighCommander4 (2017). Response to https://stackoverflow.com/questions/4184468/sleep-for-milliseconds.

StackOverflow. https://stackoverflow.com/questions/18082/validate-decimal-numbers-in-javascript-isnumeric.