-3

I need to execute 4 different pieces of code one after another with some delay. I came up with this trick to create simple sleep function but it does not render desired results.

function pauseScript (delay) {
    setTimeout(function() { return true; }, delay);
}

....
//code to be delayed
if (pauseScript(1000)) { 
    document.getElementById("message1").style.visibility='visible'; 
}
...
if (pauseScript(1000)) { 
    document.getElementById("message4").style.visibility='visible'; 
}
//code to be executed after 4 messages are revealed
Kara
  • 6,115
  • 16
  • 50
  • 57
  • 5
    Not much of a trick if it doesn't work. `setTimeout` doesn't pause a script. – the system Mar 09 '13 at 20:18
  • 3
    setTimeout queues a call for later, then returns immediately. There is no pause. – RobG Mar 09 '13 at 20:19
  • See this explanation on how javascript handles async stuff. This includes setTimeout: http://stackoverflow.com/questions/3715820/how-can-i-write-an-async-method-in-javascript-when-posting-or-looping/3716138#3716138 – slebetman Mar 09 '13 at 20:23
  • So does that mean function just returns null and later "return true;" is completely ignored by interpreter? – wannabegeek Mar 09 '13 at 20:24
  • It's ignored by the event loop, not by the iterpreter :-) – John Dvorak Mar 09 '13 at 20:25
  • 1
    To find out what the function returns, log its value. `console.log(pauseScript(1000));` – the system Mar 09 '13 at 20:25

3 Answers3

3

setTimeout does not block execution of scripts. You should do this:

setTimeout(function() {
    // code to be delayed
},1000);

In your case, you seem to have four messages to display in sequence? Try this:

setTimeout(function() {
    var f = arguments.callee;
    f.i = (f.i || 0)+1;
    document.getElementById('message'+f.i).style.visibility = "visible";
    if( f.i < 4) setTimeout(f,1000);
    else {
        // code to be run after all messages are shown.
    }
},1000);
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • 2
    does `arguments.callee` work in strict mode? I would rather see a variable in the outer scope anyways. – John Dvorak Mar 09 '13 at 20:21
  • No, but if you're working in strict mode then you can name the function and use that: `setTimeout(function counter() { var f = counter; ...},1000);`. If you want the iterator exposed to the outside scope, put `var i=0;` before the `setTimeout` and replace all mentions of `f.i` with `i`. – Niet the Dark Absol Mar 09 '13 at 20:24
  • ...but now you are using a NFE, with all the dreaded IE bugs. – Dagg Nabbit Mar 09 '13 at 20:34
  • @GGG What bugs in particular? – Niet the Dark Absol Mar 09 '13 at 20:37
  • @Kolink, you know, the old IE behavior where NFEs are actually represented by two separate function objects, etc. http://kangax.github.com/nfe/#jscript-bugs – Dagg Nabbit Mar 09 '13 at 20:38
  • Honestly I can't say I've ever used NFEs. `arguments.callee` works fine for me, and I honestly don't get why people would rather use "strict mode" when they could just write good code. – Niet the Dark Absol Mar 09 '13 at 20:45
  • @GGG: Why is that "dreaded"? – the system Mar 09 '13 at 20:54
  • `arguments.callee` probably will eventually go away entirely, so it might be a good idea to stop using it at some point. I don't think most people use NFEs either. Anyway, wouldn't it be cleaner to just put `i` in a closure instead of attaching it to the function? – Dagg Nabbit Mar 09 '13 at 20:55
  • @thesystem see the link above... attaching properties to one and assuming you'll be able to find them when you try to access them later could lead to problems down the road, since there are two copies of the object. They're leaky, they're not GC'd correctly, etc. – Dagg Nabbit Mar 09 '13 at 21:02
  • @GGG: Edge cases, and usually innocuous. Invoking or attaching properties to the function in the outer scope will fail in compliant browsers, so unless one does their primary testing in old IE, there'll be a clear error. I wouldn't let old IE's bugs slow me down. – the system Mar 09 '13 at 21:28
  • @thesystem is there ever a good reason to use a named function expression, though? Isn't it easier to just avoid it altogether rather than thinking about all the specific pitfalls to avoid? It's already an awkward construction, the history of weird browser handling is just icing on the cake. At what point do we decide that using something is bad form? – Dagg Nabbit Mar 09 '13 at 22:16
  • @GGG: Comes down to individual decisions. Personally I'd avoid `arguments.callee` in order to allow for strict mode *(which is about more than just safe code)*. NFE's aren't too often needed, and probably never *absolutely* necessary, but I'd still not throw them out.. – the system Mar 10 '13 at 00:25
0

setTimeout will not pause your script. Instead, it will schedule the function you pass to it to be executed asynchronously at a later time.

I think you are trying to do this:

setTimeout(function(){
    document.getElementById("message1").style.visibility='visible'; 
}, 1000);

setTimeout(function(){
    document.getElementById("message2").style.visibility='visible'; 
}, 2000);

setTimeout(function(){
    document.getElementById("message3").style.visibility='visible'; 
}, 3000);

setTimeout(function(){
    document.getElementById("message4").style.visibility='visible'; 
}, 4000);
DanC
  • 8,595
  • 9
  • 42
  • 64
0
function pauseScript(callbacks, delay) {
    for(var i = 0, len = callbacks.length; i < len; i++){
        setTimeout(callbacks[i], (i + 1) * delay);
    }
}

var getMessageDelegates = [
    function(){
        document.getElementById("message1").style.visibility='visible'; 
    },...,
    function(){
        document.getElementById("message4").style.visibility='visible'; 
    }
];

pauseScript(1000, getMessageDelegates);
Warlock
  • 7,321
  • 10
  • 55
  • 75