javascript sleep function

I’ve been looking for the javascript sleep function for a long time. Unfortunately, although most programming languages such as C/C++, php, python, etc. have a sleep function, javascript  has neither a sleep function nor a delay function that can pause the execution for some time and continue to execute the following code. Javascript designers are proud of this. They say if you ever have the need for a sleep function, you are on the wrong way. You should re-design your code to eliminate the need for such a function. You should split your code into several functions. This situation is analogous to Einstein’s theory of relativity to Newton’s classic theory. Although the theory of relativity is righter than Newton’s theory, I would not think about the world using the theory of relativity because that would make me crazy.  By the way, I do not think javascript is as great as the theory of relativity.

A simple alternative of the sleep function would be the following code:

function sleep(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}

But that is really a silly piece of code because it would occupy 100% CPU and freeze the web page. A smarter equivalent of the sleep function is:

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

This function is actually an asynchronous function which returns(a Promise object) immediately. So how does it simulate the sleep behavior? Well, you can use the “await” operator before the calling of the  async function.

await sleep(2000);

Now this line will pause 2000 milliseconds then execute the following code. await, as the name implies, will wait for the returned Promise object to reach the fulfilled status. Now you should understand what the Promise object is.

When constructing a Promise object, you need to pass a function called executor as the parameter of the construction function. The function should have a resolve parameter and an optional reject parameter. The executor is called as soon as you new the Promise object. When the executor is called, it is passed two parameters by the system. The actual parameters are the system-defined resolve and reject function. I mean, you can use other names for the parameters when you define the executor like this:

function(myresolve,myreject)
{
    .....
    if(success)
      myresolve(0);
   else
      myreject(1);
}

But when the function is called, myresolve will be passed as the system-defined resolve and myreject will be passed as the system-defined reject. The system-defined resolve function will set the status of the Promise object from the initial pending status to fulfilled status. The system-defined reject function will change the status from the initial pending status to the rejected status. The status, after changed, will keep the same forever.

Now look back at our sleep function. The parameter passed when constructing the Promise object is not an ordinary function, but a lambda expression. A lamda expression essentially defines an anonymous function, the name before the arrow is the parameter(s) of the function. You should use brackets to enclose multiple parameters. If the function has no parameter, you should use a pair of brackets (containing nothing) in there. The stuff after the arrow is the function body. Here we call the setTimeout function to set the Promise object to the fulfilled status after specific time, in order for await to return.

That is not the whole story. In order to use await, you should include your code in an async function:

async myfun()
{
  dosomething;
  await sleep(5000);//sleep 5 seconds
  do something else;
}

myfun();

When you call an async function like myfun, it will return a Promise object immediately when it meets the await line. The current task(function) myfun will be put into the wait queue, and the code after the call of myfun will be executed. After all the subsequent code is executed, it will enter the event loop, where it will pick up the waiting task(myfun) and execute the task. This means if you put the sleep function in different async functions, you may not get  the expected result:

async fun1()
{
     dosomething1;
     await sleep(1000);
     dosomething2;
}

async fun2()
{
    dosomething3;
}

fun1();
fun2();

You want to dosomething1, wait 1000 ms, then dosomething2, then dosomething3 at last. But the result is dosomething1, then dosomething3, and dosomething2 at last.

 

Leave a Reply