0

I understand that there is not a native sleep or wait method in JavaScript. However, I am aware of the setTimeout method, and I am trying to use it to delay execution within a loop.

I am trying to delay the printing of the iteration (i.e. 0, 1, 2) in three second intervals.

function load () {
  for (var i = 0; i < 3; i++) {
      console.log(i);
      setTimeout(function() {console.log('sleeping three seconds')}, 3000);
  }
}

This outputs:

0
1
2

and after three seconds

(3) sleeping three seconds 

However, I'm trying to have a three second pause between iteration, so that I have execution as:

0
sleeping three seconds 
1 
sleeping three seconds 
2
sleeping three seconds
Kyle
  • 1,153
  • 5
  • 28
  • 56
  • 1
    _"I understand that there is not a native sleep or wait method in JavaScript. However, I am aware of the setTimeout method, and I am trying to use it to delay execution within a loop."_ - which you simply can not do. You are not delaying anything here - you are simply creating three timeouts, each to fire after three seconds, almost simultaneously, so that's what they do. – CBroe Jun 10 '17 at 17:48

4 Answers4

1

The loop finishes right away, it doesn't wait for anything, so all the timeouts you've created executes in three seconds from now !

If you want to increment the delay, multiply it by the iterator

function load() {
  for (var i = 0; i < 3; i++) {
    setTimeout(function() {
      console.log('sleeping three seconds');
    }, 3000 * (i + 1));
  }
}

load();
adeneo
  • 312,895
  • 29
  • 395
  • 388
1

Another way (imho quite elegant) of doing that would be to call the function recursively. Something like:

function load(i) {
  if (i <= 3) {
    console.log(i);
    console.log("sleeping 3 seconds");
    setTimeout(function() {load(i + 1)}, 3000);
  }
}
load(0);
BoltKey
  • 1,994
  • 1
  • 14
  • 26
  • That's interesting because I was using a recursive function callback in one of my examples (not posted in question), but it appears to only work if the recursive callback is wrapped in an anonymous function. Can you explain why? – Kyle Jun 10 '17 at 18:33
  • For example: `setTimeout(load(i + 1), 3000)` does not execute the same as `setTimeout(function() load(i + 1)}, 3000)` – Kyle Jun 10 '17 at 18:35
  • @kyle.belanger best would be setTimeout(load,3000,i+1); – Jonas Wilms Jun 10 '17 at 18:40
  • @Kyle.Belanger Well, you need to pass a function as a parameter. The problem with the first example is that the function gets called immediately, and returns `undefined` to be used as the `setTimeout` parameter (which we obviously don't want). However, if you write it like I did in my example, the parameter value is indeed a function. @Jonasw Yes, that would probably be a bit better, but I felt like an anonymous function is a bit less confusing than third parameter. – BoltKey Jun 10 '17 at 19:14
0

Theres something like wait called await :

function timer(v){
 return new Promise(r=>setTimeout(r,v));
}

async function load () {
 for (var i = 0; i < 3; i++) {
  console.log(i);
  await timer(3000);
  }
}

load();

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

Note that this is ES7, so you need to transpile with Babel to use it everywhere.

Transpiled

Community
  • 1
  • 1
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
0

You could add a delay function to the standard browser promise implementation:

Promise.prototype.delay = Promise.prototype.delay || function (ms) {
    return this.then(function () {
        let args = arguments;
        return new Promise(function (resolve) {
            setTimeout(function () {
                resolve.apply(this, args);
            }, ms);
        });
    });
};

After that your function could look like this:

let load = function () {
    let promise = Promise.resolve();
    for (let i = 0; i < 3; i++) {
        promise = promise.delay(3000).then(() => console.log(i) );
    }
};

load();

This implementation should work in all major browsers (not in IE 11): https://caniuse.com/#search=Promise

Artem Stepin
  • 421
  • 5
  • 13