为什么闭包不能通过异步获得正确的外部值?
问题描述:
见与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]
?
答
因为每个呼叫在calls
阵列引用相同i
变量,认为这样的代码:
function fn() {
var i = 1;
setTimeout(function() { alert(i); }, 500);
i++;
i++;
}
fn();
此,当然,将输出代替,这是您的代码的相同问题,变量i
在执行调用之前已更改;
为了避免这个问题,包为循环与立即调用函数表达式创建一个新的范围,以存储i
for (var i = 0; i < 3; i++) {
(function(i) {
calls.push(function(cb) { inc(i, cb); });
}(i));
}
值
答
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));
}