See the following nodejs code with async:
var async = require('async');
function inc(n, cb) {
setTimeout(function() {
cb(null, n+1);
},1000);
};
var calls = [];
for(i=0;i<3;i++) {
calls.push(function(cb){
inc(i, cb);
});
}
async.parallel(calls, function(err, results) {
console.log(results);
});
It prints:
[4, 4, 4]
I don't understand why the result isn't [1, 2, 3]
?
for(i=0;i<3;i++) {
calls.push(function(cb){
inc(i, cb);
});
}
The functions are getting executed after the end of the for
loop; at the time, i
equals 3
.
You should use another closure here. For example:
for(i=0;i<3;i++) {
calls.push(function (i) {
return function (cb) {
inc(i, cb);
}
}(i));
}
Because every call in calls
array references the same i
variable, think this code:
function fn() {
var i = 1;
setTimeout(function() { alert(i); }, 500);
i++;
i++;
}
fn();
This, certainly, would output 3 instead of 1, this is the same issue of your code, the variable i
changed before the call executes;
To avoid this problem, wrap for loop with a Immediately Invoked Function Expression to create a new scope to store the value of i
for (var i = 0; i < 3; i++) {
(function(i) {
calls.push(function(cb) { inc(i, cb); });
}(i));
}