2

请参阅以下带有async的 nodejs 代码:

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);
});

它打印:

[4, 4, 4]

我不明白为什么结果不是[1, 2, 3]

4

2 回答 2

2
for(i=0;i<3;i++) {
    calls.push(function(cb){
        inc(i, cb);
    });
}

for函数在循环结束后执行;当时,i等于3

你应该在这里使用另一个闭包。例如:

for(i=0;i<3;i++) {
    calls.push(function (i) {
        return function (cb) {
            inc(i, cb);
        }
    }(i));
}
于 2012-05-15T06:00:33.180 回答
2

因为数组中的每个调用calls引用相同的i变量,所以请考虑以下代码:

function fn() {
    var i = 1;
    setTimeout(function() { alert(i); }, 500);
    i++;
    i++;
}
fn();

这当然会输出3而不是1,这是您的代码的同一个问题,变量在调用执行i之前发生了变化;

为避免此问题,请使用立即调用函数表达式包装for循环以创建一个新范围来存储i

for (var i = 0; i < 3; i++) {
    (function(i) {
        calls.push(function(cb) { inc(i, cb); });
    }(i));
}
于 2012-05-15T06:02:10.937 回答