Ben Quan
Ben Quan

Reputation: 817

Javascript Promise Variable Scope in For Loop

Newbie alert!

I'm trying to understand the variable scope for a promise inside a for loop.

Consider the following code:

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

for (var i =0; i<4; i++){
  sleep(1000).then(() => console.log(i));
}

The promise is called 4 times at once and then responds with:

4
4
4
4

How can I keep reference to the i variable? In order to get

0
1
2
3

Or whatever execution order actually took place.

Upvotes: 1

Views: 1441

Answers (3)

Ben Quan
Ben Quan

Reputation: 817

As pointed out by ASDFGerte, by changing var to let, the i variable is kept within the block and outputs the desired reference.

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

for (let i=0; i<4; i++){
  sleep(1000).then(() => console.log(i));
}

Upvotes: 1

Thatalent
Thatalent

Reputation: 424

Your problem is just how you're calling your sleep function. You must use the await keyword inside of an async labeled function.

This should be how your code looks:

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

async function printSleep(){
for (var i =0; i<4; i++){
  await sleep(1000).then(() => console.log(i));
}
}

printSleep();

The key part you're missing is that you must use await to actually have your code wait for the sleep function to finish. If you don't it will queue the function and continuing executing the rest of the function in a synchronous fashion, causing your then statement to execute after the for loop has finished.

Upvotes: 1

XPX-Gloom
XPX-Gloom

Reputation: 601

You can pass the i into the sleep function and resolve it.

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

 for (var i = 0; i < 4; i++){
   sleep(i, 1000).then((data) => console.log(data));
 }

Upvotes: 1

Related Questions