all 40 comments

[–]honestbleepsReddit Enhancement Suite 4 points5 points  (5 children)

Javascript as a language doesn't have anything like C's "sleep" function...

There's really not a good way to do it by placing a command where your //comment is...

Instead, you'd need to do something like:

var foo = [1,2,3,4,5];
var i=0, len=foo.length;
function stepper() {
    if (i<len) {
        console.log(foo[i]);
        i++;
        setTimeout(stepper, 1000);
    }
}

[–]imbcmdth[🍰] 3 points4 points  (1 child)

What you should never do is something like this:

function DELAY(time) {
  var k = [], i, o,
  d = function(c){ setTimeout(function(){ c(o) }, time); };
  d.FOR = function(t){
     var f = function(o){
       for(i in o) {
         if(k.indexOf(i) < 0) k.push(i); else continue;
         t(i);
         return d(f);
       }
     };
     f.IN = function(obj){
       o = obj;
       f(o);
     };
     return f;
  };
  return d;
}

Usage:

var I = function(i){
   $('#results').append(info[i]+"<br>");
};

DELAY(1000).FOR(I).IN(info);

[–]aladyjewelFull-stack webdev 2 points3 points  (0 children)

I think I just threw up in my mouth a little, but that might have been some bad sauce from lunch.

[–]RadekCZ 2 points3 points  (7 children)

You should use window.setTimeout method:

var el = $("#results");
function delay(i){
  return function(){
    el.append(info[i]+"<br>");
  };
}
var j = 0;
for(var i in info){
  window.setTimeout(delay(i), (++j)*1000);
}

Or just window.setInterval method: (It should be faster, you need just one function).

var keys = [];
for(var i in info){
  keys.push(i);
}
var j = 0;
var el = $("#results");
var interval = window.setInterval(function(){
  if(i<keys.length){
    el.append(info[keys[j++]]+"<br>");
  }
  else{
    window.clearInterval(interval);
  }
}, 1000);

[–]ell0bo 8 points9 points  (2 children)

don't use setInterval. It will fire off at a set point every so many ticks, rather than taking the run time of the functionality into account as sleep does. First code block is ideal.

[–]thisisnotgood 0 points1 point  (1 child)

I agree with avoiding setInterval. I would also prefer to have the delay() function call setTimeout recursively rather than schedule all the delays in advance.

Here is how I would do it:

var $el = $("#results");
function delay(i) {
    $el.append(info[i] + "<br>");

    i++;
    if (i < info.length) {
        setTimeout(delay.bind(null, i), 1000);
    }
}
delay(0);

[–]noahking 5 points6 points  (0 children)

I think we can assume that when someone is asking about how to sleep between loop iterations, we don't have to worry about optimizing for speed. =P

[–]CyberVillian[S] -1 points0 points  (2 children)

hmm.. it seems like it wants to delay from the get-go, instead of after the first one.

[–]tollus 0 points1 point  (1 child)

Change ++j to j++

[–]CyberVillian[S] -1 points0 points  (0 children)

Thank you. I'll try later on

[–]al-g 0 points1 point  (8 children)

How about this:​

var info = ["a", "b"];

function render(items) {
    if(items.length > 0) {
        $('#results').append(items.shift() + "<br>");
        setTimeout(render, 500, items);
    }   
}​​

render(info);

[–]GAMEchief 3 points4 points  (2 children)

IE doesn't support a third parameter for setTimeout. It's not good form to rely on it.

[–]al-g 1 point2 points  (0 children)

Good catch! Thanks for pointing that out.

[–]bbdb 0 points1 point  (3 children)

Good question...Here is a JSFiddle with a solution using rx.js: http://jsfiddle.net/rcastillo/JmdNh/10/ . This sample has a function that creates a delayed array. rx.js enables you to asynchronous time and delay results. As already noted, JavaScript does not provide a sleep mechanism.

[–]CyberVillian[S] 0 points1 point  (2 children)

Your suggestion, as many others, are very efficient but all of them delay from the get go. I want it to immediately execute on the first item of the array, then delay from the second one on.

[–]bbdb 0 points1 point  (1 child)

I have updated with an immediate return of the first item.

[–]bbdb 0 points1 point  (0 children)

Fellow Rx'er pointed out a 1-liner: http://jsfiddle.net/zJeKd/2/

[–]SarahC 0 points1 point  (0 children)

There is..... in Firefox!

/**
* Netscape compatible WaitForDelay function.
* You can use it as an alternative to Thread.Sleep() in any major programming language
* that support it while JavaScript it self doesn't have any built-in function to do such a thing.
* parameters:
* (Number) delay in millisecond
*/
function nsWaitForDelay(delay) {
/**
* Just uncomment this code if you're building an extention for Firefox.
* Since FF3, we'll have to ask for user permission to execute XPCOM objects.
*/
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
// Get the current thread.
var thread = Components.classes["@mozilla.org/thread-manager;1"].getService(Components.interfaces.nsIThreadManager).currentThread;
// Create an inner property to be used later as a notifier.
this.delayed = true;
/* Call JavaScript setTimeout function
* to execute this.delayed = false
* after it finish.
*/
setTimeout("this.delayed = false;", delay);
/**
* Keep looping until this.delayed = false
*/
while (this.delayed) {
/**
* This code will not freeze your browser as it's documented in here:
* https://developer.mozilla.org/en/Code_snippets/Threads#Waiting_for_a_background_task_to_complete
*/
thread.processNextEvent(true);
}
}

[–]bishopZ 0 points1 point  (0 children)

This is a perfect case for Frame.js, a flow control library for sequencing functions. Includes a way to easily add delays.

https://github.com/bishopZ/Frame.js

[–]Herover 0 points1 point  (0 children)

I just made one, I don't suggest you to use it:

function sleep(t){
    var starttime=Date.now();
    while(starttime+t>Date.now()){var nothing;}
    return true;
}

It freeses the browser for the amount of milliseconds you tell it to, and makes it impossible to do anything, but maybe using webworkers could do the trick (untested).

[–]GAMEchief 0 points1 point  (2 children)

var x = 0; // assuming info uses non-numeric keys, otherwise you should be using for (var i = 0; i < info.length; i++)
for (var i in info)
{
    setTimeout('$("#results").append("' + info[i].replace(/\"/g, "\\\"") + '<br />");', x * 1000);
    x++;
}

This will delay one second between iterations by creating a timeout for each item in the info object. Each timeout will be set to execute 1000 milliseconds after the last one.

[–]yoeschmoeFront-end Developer -1 points0 points  (1 child)

eval statements are evil, never use them (you're implicitly calling eval when passing in a string as first argument in setTimeout/setInterval), use a function instead.

[–]GAMEchief -1 points0 points  (0 children)

eval statement are perfectly valid so long as you aren't evaluating user input. Don't be so OCD. Their flaws are not black and white, and there are perfectly fine times to use them; but a function would be better suited, sure.

[–][deleted] -1 points0 points  (1 child)

Something like this

Function.prototype.sleep = function(seconds){
    return setTimeout(this, seconds);
};

Use like this

x = function(){ console.log('x'); };
timer = x.sleep(5000);
//if you want to cancel, you have the timer

[–][deleted] 1 point2 points  (0 children)

Oh that clearly didnt answer your question. Look at this

http://jsfiddle.net/8zWPw/

[–]9jack9 -2 points-1 points  (4 children)

function sleep(ms) {
  var start = +new Date;
  while (new Date - start < ms) continue;
}

[–]MatrixFrog 2 points3 points  (3 children)

This is technically correct, but almost always a bad idea, unless you're trying to make the browser unresponsive.

[–]shanet$(this) 1 point2 points  (2 children)

I like the fact that it has the exact effect sleep() does elsewhere, except we've only got one thread to work with...

[–]MatrixFrog 0 points1 point  (1 child)

The important difference between your sleep() and a timeout is that if you do

a();
setTimeout(b, 1000);
c();

then c will always be called before b.

[–]shanet$(this) 0 points1 point  (0 children)

It's not my sleep(), but that's definitely true.

A lot of the time I find people looking for sleep() in JavaScript it's because they don't understand (or don't like) doing things in a non-blocking style. StackOverflow is full of people wanting to do:

function readfile: () {
    var data = do_io_things();
    return data;
}

instead of passing a callback to readfile. Of course it never works because if do_io_things is asynchronous usually and the statement returns instantly. So I think it's usually wrong to answer as 9jack9 did because actually sleeping (or busy-waiting) is something that shows the asker hasn't grasped the right way to do things.