为什么闭包没有使用异步获得正确的外部值?

时间:2012-05-15 05:58:35

标签: javascript node.js asynchronous

使用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]

2 个答案:

答案 0 :(得分: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));
}

答案 1 :(得分: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));
}