Home>

I don't understand the output result of the following code (all 11 lines)!

const psvar = [];
for (var i = 0;i<5;i ++) {
  psvar.push (new Promise (resolve =>{
    setTimeout (() =>{
      resolve (i);
    }, 0);
  }));
}
Promise.all (psvar) .then (results =>{
  console.log (results);// [5, 5, 5, 5, 5]
});

Why is the output result [5, 5, 5, 5, 5] instead of [0, 1, 2, 3, 4]?
Please let me know if you know.

Postscript

Just declare index variable i with let instead of var.
The output result is [0, 1, 2, 3, 4] as expected.

Why is this too?
JavaScript is too difficult><

const pslet = [];
for (let i = 0;i&lt;5;i ++) {
  pslet.push (new Promise (resolve =&gt;{
    setTimeout (() =&gt;{
      resolve (i);
    }, 0);
  }));
}
Promise.all (pslet) .then (results =&gt;{
  console.log (results);// [0, 1, 2, 3, 4]
});

↓ Added by editing

If setTimeout is declared externally,
Even if the declaration of index variable i is var
I found that the output was as expected [0, 1, 2, 3, 4].
Why is this too?

const ps = [];
const getPromise = (i) =&gt;{
  return new Promise (resolve =&gt;{
    setTimeout (() =&gt;{
      resolve (i);
    }, 0);
  });
};
for (var i = 0;i&lt;5;i ++) {
  ps.push (getPromise (i));
}
Promise.all (ps) .then (results =&gt;{
  console.log (results);// [0, 1, 2, 3, 4]
});
const psvar = [];
const doSetTimeout = (func, i) =&gt;{
  setTimeout (() =&gt;{
    func (i);
  }, 0);
};
for (var i = 0;i&lt;5;i ++) {
  psvar.push (new Promise (resolve =&gt;{
    doSetTimeout (resolve, i);
  }));
}
Promise.all (psvar) .then (results =&gt;{
  console.log (results);// [0, 1, 2, 3, 4]
});
  • Answer # 1

    var and let

    varis a function scope, so it shares the scope of the variable i, and the value ofiwhen calling the timer function registered withsetTimeoutIs 5.
    Sinceletis block scope, it doesn't share the scope of variable i.

    Another solution

    Aside from that, it's an idea to waste the closures and put pressure on the memory.

    const ps = [];
    for (let i = 0;i<5;i ++) {
      ps.push (new Promise (resolve =>setTimeout (resolve, 0, i)));
    }
    Promise.all (ps) .then (console.log.bind (console));

    When the scope is narrowed to the limit (friendly to Garbage Collection).

    (function () {
      function createPromise (i) {
        return new Promise (resolve =>setTimeout (resolve, 0, i));
      }
      {
        const ps = [];
        for (let i = 0;i<5;i ++) {
          ps.push (createPromise (i));
        }
        Promise.all (ps) .then (console.log.bind (console));
      }
    } ());

    Re: yuzunoha123-san

  • Answer # 2

    If you declare a loop variable withvar, it is just the same variable you declared at the beginning of the function. So, if you read the variable in the process of asynchronous execution, you will get 5 after the end of the loop.

    On the other hand, declaring a loop variable withletis quite special. I examined it when I answered another question before, but thisletis treated as a separate variablefor eachloop. So, even if the next loop turns,iinPromiseremains as it is, and the value generated in the loop is saved. It is.