-2

Here is a the simplest function:

module.exports = function Dummy(id) {
    this.id = id;

    this.delay = function() {
        return new Promise(function (resolve, reject) {
            // Do some stuff async
            // once done
            resolve();
        });
    }
}

I want to instantiate a few instances of this Dummy() class inside a for loop:

for (var i = 0; i < 3; i++) {
    var id = "id_" + i;
    var dummy = new Dummy(id);

    dummy
        .delay()
        .then(function () {
            console.log(dummy.id);
        });
}

However, all of these print id_2; its as though the instant dummy is overwritten, even though I am instantiating the variable var dummy every time inside the for loop.

Help is appreciated.

Kousha
  • 32,871
  • 51
  • 172
  • 296

2 Answers2

2

There is a closure problem with the variable called dummy inside the then function. The value will be the last iterated because every iteration of the for will override the previous one. It means that when the then function is executed asynchronously (due to the promise you are using) the value of the dummy var will be the last value assigned during the loop.

To fix it I suggest to simply do this instead:

for (var i = 0; i < 3; i++) {
    (function (id) { //Creates a simple new scope
        var dummy = new Dummy(id);

        dummy
            .delay()
            .then(function () {
                console.log(dummy.id);
            });
    })("id_" + i);
}

There are lots of ways to fix this but I think that is the simplest for your current code.

As you may noticed, for every for iteration I have created a new scope. When the then function is executed, it will access to the dummy var in that scope.

José Cabo
  • 6,149
  • 3
  • 28
  • 39
  • You need to love javascript, if there's a closure issue, simply add another function. Value will not be last, but 'current'. –  Aug 02 '15 at 22:59
  • What do you mean? Are you complaining about my solution? As I have said there are lots of ways to fix this problem. Actually, I usually don't have it because my architecture avoid this kind of problems. Scoping in JavaScript is just an awesome feature, but it is not the only. – José Cabo Aug 02 '15 at 23:02
  • And YES. I LOVE javascript :) No problem to admit it :) – José Cabo Aug 02 '15 at 23:02
  • 1
    Didnt complain, gave you an upvote as well ;P –  Aug 02 '15 at 23:03
0

It's because when console.log happens, dummy is id_2.

.then(function () {
  console.log(dummy.id);
});

The promises will be queued and resolve after the execution of the for loop. Once the promise resolves dummy is the value of the last iteration.

Kit Sunde
  • 35,972
  • 25
  • 125
  • 179