0

When I run the following code, there's some problem with my code.

Expected result:

['test0,'test1','test2']

Actual result:

['test3','test3','test3']

Code:

var overall = [];

for(var a=0;a<3;a++){
    var test_promise = new Promise(function(resolve,reject){
        setTimeout(()=>{
            console.log("looping: " + a);
            resolve('test' + a);
        },3000);
    });

    overall.push(test_promise);
}

Promise.all(overall).then(function(value){
    console.log(value);
});
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
alexlee11111
  • 87
  • 1
  • 10

4 Answers4

2

To fix it , you should change var to let in for loop ( closure problem)

for(let a=0;a<3;a++)

The above result is because, var defines variable globally, or locally to an entire function regardless of block scope.

let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope.

for example

for(var i = 1; i <= 5; i++) {
   setTimeout(function() {
       console.log('Value of i : ' + i); 
   },100);
} 

The desired output of the above code is

Value of i : 1
Value of i : 2
Value of i : 3
Value of i : 4
Value of i : 5

But the actual output is

Value of i : 6
Value of i : 6
Value of i : 6
Value of i : 6
Value of i : 6

The above result is because, var defines variable globally, or locally to an entire function regardless of block scope.

for(let i = 1; i <= 5; i++) {

   setTimeout(function(){
       console.log('Value of i : ' + i);
   },100);
}
Output:
Value of i : 1
Value of i : 2
Value of i : 3
Value of i : 4
Value of i : 5

in your case, your code will be:

for(let a=0;a<3;a++){
    var test_promise = new Promise(function(resolve,reject){
        setTimeout(()=>{
            console.log("looping: " + a);
            resolve('test' + a);
        },3000);
    });

    overall.push(test_promise);
}
Ghoul Ahmed
  • 4,446
  • 1
  • 14
  • 23
0

You need to use let and pass the value into the promise like so:

 

var overall = [];

for(let a=0;a<3;a++){
(aa => {
let test_promise = new Promise(function(resolve,reject){
    setTimeout(()=>{
        console.log("looping: " + a);
        resolve('test' + aa);
    },3000);
});

overall.push(test_promise);
})(a);
}

Promise.all(overall).then(function(value){
console.log(value);
});
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
0

quick answer: use let a = 0 instead of var a = 0

longer answer: var is hoisted globalled and let and const are hoisted based on the current scope. So when you push to the array after the timeout, it tke the current value of a aka the last iteration of the for loop. While using const or let, the value of a a the creattion of your promise will be used in the closure.

Bassochette
  • 166
  • 1
  • 1
  • 13
0

Instead of using var in for loop, use let. You can get the better idea about var and let from here Difference between var and let?

var overall = [];

for(let a=0;a<3;a++){
    var test_promise = new Promise(function(resolve,reject){
        setTimeout(()=>{
            console.log("looping: " + a);
            resolve('test' + a);
        },3000);
    });

    overall.push(test_promise);
}

Promise.all(overall).then(function(value){
    console.log(value);
});
Shivani Sonagara
  • 1,299
  • 9
  • 21