To sleep with javascript

By Andrew Smith

All proper programming languages I can think of have a real simple function – sleep(). It suspends the execution of your program for a time. This is what I wanted to do. Having no choice but to use javascript in this case, I went around looking for what the sleep() function is called in this dreadful language.

Turns out there is none. There is only setTimeout() and setInterval(). Either will call a function after a time, but in between your code will continue to execute.

All I could find on the internet is a bunch of solutions to this problem involving an infinite loop. That, for I hope obvious reasons, was not acceptable for me.

I considered using `yield` but that doesn’t work for some reason in my version of the current firefox trunk. I did the javascript version thing, but then none of the javascript I had (yield or not) would work at all.

So I grumbled for a couple of hours and finally figured out a solution so my stuff still works as I want it, and all that’s lost is readability. I’ll share this beast with you all in case you ever run into the same problem.

This is what I wanted done in the first place, overly simplfied (lack of whitespace courtesy of wordpress):

function wish(i, j)
{
var k = i + j;

for(var m = 0; m < 10; m++)
{
// start doing something outside of my control

sleep(5000); // sleep for 5 seconds

// check the results of the something

alert(k + “, ” + m + results);
}
}

Like I said, it’s overly simplified. There’s no need to bring 3D and benchmarks into this example.

Since setInterval() is all I have to work with, that’s what I’ll use. The tricks to address my concerns are:

  1. Make a global function that will take the (i, j) parameters and have it call another function (real()) that doesn’t take any parameters
  2. Copy the parameters to wish() into glabal variables
  3. Where the sleep() would be have a setInterval(‘real()’, 5000) instead
  4. Copy all the local variables in real() to global variables before the setInterval()
  5. Add a condition so real() will know whether it should continue from where it left off or start from the beginning.

A lot of work, but the other option is to not do it at all.. Here’s what it now looks like:

var gI;
var gJ;

function wish(i, j)
{
gI = i;
gJ = j;
real();
}

var gK;
var gM = 0;
var didSleep = false;

function real()
{
if (didSleep)
{
// check the results of the something
alert(gK + “, ” + (gM – 1) + results);
}
else
{
gK = gI + gJ;
}

for(m = gM; m < 10; m++)
{
// start doing something outside of my control

gK = k;
gM = m + 1;
didSleep = true;
setInterval(“real()”, 5000);
return;
}
}

That’s pretty disgusting. I’d blame the people who came up with javascript if it wasn’t for the fact that javascript was never designed to be a proper language. Javascript was made for people one level above HTML, which is far, far from real programming and it served those people well.

Instead I blame the people responsible for the javascript hype. Both the fanboys who don’t know any better but their strength is in numbers; and the programmers who sell their time/ideas by proclaiming that AJAX is the only way to go. I even blame google a little for making the two useful javascript applications in the world.

I’ll say it again – disgusting.

5 Responses to “To sleep with javascript”

  1. Mike Shaver Says:

    I should add that if you want to use generators to emulate parallel flows of control, you can do so on top of yield. Someone who doesn’t understand closures is unlikely to have a good time implementing it from scratch, but happily you don’t have to: http://www.neilmix.com/2007/02/07/threading-in-javascript-17/

  2. Mike Shaver Says:

    [Think this bounced off because of some angle brackets in my code snippet; hard to tell without preview.]

    I think the designer of JavaScript would tell you otherwise about the design goals; it’s not hard to find very experienced language designers and developers who will praise JavaScript’s use of delegation and first-class functions as powerful tools, but if you try to write C in JavaScript, you’ll hurt. Just as if you tried to write Lisp in C, or Fortran in shell. (Said designer used to be a co-worker of yours; you could have asked him about it!)

    I don’t know why you need globals, though; can’t you just pass a closure to setInterval?

    (The timer and theoretical sleep functions in question belong to the DOM, not to the language, as many languages have a distinction between runtime and language. JavaScript’s run-to-completion semantics are important for coherence on the web, and mean that you can’t have any response to script action on a page when a putative sleep(5000) was sleeping. It would be like putting a sleep(5000) in a GTK event handler in your beloved C: you’d lock up the app for 5 seconds at a time. Non-web embeddings can and do have sleep() functions in them; the JS shell in the mozilla tree is such an example. Not that you seem to care about learning what JavaScript is actually good for, or how it can be used successfully, since you have already made up your mind permanently after that first weekend of naive hacking, but other people might read your post who aren’t as closed-minded. JS definitely has its flaws, and the DOM in which its embedded even more so, as anyone with non-trivial experience with it will tell you readily. + as string and integer operator both? with? the value of delete expressions? The list definitely goes on, but there’s no language without a similar list of flaws.)

    function wish(i, j)
    {
    var k = i + j;
    var m = 0, max = 10;

    function heartbeat() {
    alert(k + “, ” + m + results);
    if (++m greaterthanorequalto 10)
    cancelTimeout(timeout);
    }

    var timeout = setInterval(heartbeat, 5000);
    }

    Untested, but a pattern that’s widely used, and doesn’t involve global variables or other such mess. Not knowing how to use closures in JS is like not knowing how to use pointers in C: I don’t think you would think very highly of someone who said “C sucks! it’s so ugly to manage state between caller and callee!” but didn’t bother using pointers to do it.

  3. Andrew Smith Says:

    Ah, so a sleep() would block everything the browser? I thought the reason there’s no sleep() might be something like that.

  4. matt Says:

    This article does nothing other than to show your lack of JavaScript knowledge. I’m not sure why you assumed that something couldn’t be done just because you couldn’t figure it out. JavaScript is very powerful and can emulate sleep() type behavior trivially. To see this behavior used extremely well, see: http://developer.yahoo.com/yui/yuitest/

  5. therealdealsince1982 Says:

    I have searched/googled quite a few webpages on javascript sleep/wait… and there is NO answer if you want javascript to “RUN, DELAY, RUN”… what most people got was either, “RUN, RUN(useless stuff), RUN” or “RUN, RUN + delayed RUN”….

    So I ate some burgers and got thinking:::
    here is a solution that works… but you have to chop up your running codes…:::

    replace <.. with < to run..
    //…………………………………..
    //example1:

    DISPLAY

    //javascript sleep by “therealdealsince1982″; copyrighted 2009
    //setInterval
    var i = 0;

    function run() {
    //pieces of codes to run
    if (i==0){document.getElementById(“id1″).innerHTML= “code segment “+ i +” is ran”; }
    if (i==1){document.getElementById(“id1″).innerHTML= “code segment “+ i +” is ran”; }
    if (i==2){document.getElementById(“id1″).innerHTML= “code segment “+ i +” is ran”; }
    if (i >2){document.getElementById(“id1″).innerHTML= “code segment “+ i +” is ran”; }
    if (i==5){document.getElementById(“id1″).innerHTML= “all code segment finished running”; clearInterval(t); } //end interval, stops run
    i++; //segment of code finished running, next…
    }

    t=setInterval(“run()”,1000);

    //………………………………
    //example2:

    DISPLAY

    //javascript sleep by “therealdealsince1982″; copyrighted 2009
    //setTimeout
    var i = 0;

    function flow() {
    run(i);
    i++; //code segment finished running, increment i; can put elsewhere
    sleep(1000);
    if (i==5) {clearTimeout(t);} //stops flow, must be after sleep()
    }

    function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById(“id1″).innerHTML= “code segment “+ segment +” is ran”; }
    if (segment==1){document.getElementById(“id1″).innerHTML= “code segment “+ segment +” is ran”; }
    if (segment==2){document.getElementById(“id1″).innerHTML= “code segment “+ segment +” is ran”; }
    if (segment >2){document.getElementById(“id1″).innerHTML= “code segment “+ segment +” is ran”; }
    }

    function sleep(dur) {t=setTimeout(“flow()”,dur);} //starts flow control again after dur

    flow(); //starts flow

    //……………………………….
    //example3:

    DISPLAY

    //javascript sleep by “therealdealsince1982″; copyrighted 2009
    //setTimeout, switch
    var i = 0;

    function flow() {
    switch(i)
    {
    case 0:
    run(i);
    sleep(1000);
    break;
    case 1:
    run(i);
    sleep(2000);
    break;
    case 5:
    run(i);
    clearTimeout(t); //stops flow
    break;
    default:
    run(i);
    sleep(3000);
    break;
    }
    }

    function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById(“id1″).innerHTML= “code segment “+ segment +” is ran”; }
    if (segment==1){document.getElementById(“id1″).innerHTML= “code segment “+ segment +” is ran”; }
    if (segment==2){document.getElementById(“id1″).innerHTML= “code segment “+ segment +” is ran”; }
    if (segment >2){document.getElementById(“id1″).innerHTML= “code segment “+ segment +” is ran”; }
    i++; //current segment of code finished running, next…
    }

    function sleep(dur) {t=setTimeout(“flow()”,dur);} //starts flow control again after dur

    flow(); //starts flow control for first time…

Leave a Reply