在异步回调中使用 _.after(),污染数组变量
Using _.after() in async callback, polluting array variable
我希望这个问题不是重复的,我在这里搜索过类似的问题但没有找到匹配的结果。
In node.js 下面的代码污染了 storage
变量。我真的想不通为什么。
var _ = require('underscore'); // same result by using lodash
function add(arr, callback) {
var l = arr.length,
storage = [];
function doCallback() {
callback(storage);
}
returnStorage = _.after(l, doCallback);
_.each(arr, function (a) {
_.delay(function () {
storage.push(a);
returnStorage();
}, 10);
});
}
function callbackHandler(result) {
console.log(result);
}
add([1,2,3], callbackHandler),
add([4,5,6,7], callbackHandler);
// in console will print wrong result:
// [ 4 ]
// [ 4, 5 ]
// [ 4, 5, 6 ]
// [ 4, 5, 6, 7 ]
但是,如果我不使用 _.after()
,它将给出预期的结果。使用 underscore 或 lodash 得到相同的结果。
下面的代码工作正常。
var _ = require('underscore'); // same result by using lodash
function add(arr, callback) {
var l = arr.length,
storage = [];
function returnStorage() {
if (storage.length == l) {
callback(storage);
}
}
_.each(arr, function (a) {
_.delay(function () {
storage.push(a);
returnStorage();
}, 10);
});
}
function callbackHandler(result) {
console.log(result);
}
add([1,2,3], callbackHandler),
add([4,5,6,7], callbackHandler);
// in console will print correct result:
// [ 1, 2, 3 ]
// [ 4, 5, 6, 7 ]
我应该如何确定根本原因!
javascript 上下文的魔力。当你在做的时候:
returnStorage = _.after(l, doCallback);
returnStorage
与您第二次调用 add
相同。
您需要用 var
声明它,使其成为函数的新函数和本地函数。
var _ = require('underscore'); // same result by using lodash
function add(arr, callback) {
var l = arr.length,
storage = [];
function doCallback() {
callback(storage);
}
var returnStorage = _.after(l, doCallback);
_.each(arr, function (a) {
_.delay(function () {
storage.push(a);
returnStorage();
}, 10);
});
}
function callbackHandler(result) {
console.log(result);
}
add([1,2,3], callbackHandler),
add([4,5,6,7], callbackHandler);
// in console:
// [ 1, 2, 3 ]
// [ 4, 5, 6, 7 ]
一点解释:
在您第一次调用 add()
时,returnStorage
是 undefined
。然后它将被定义为全局上下文,因为它们之前没有 var
。
在第二次调用时,变量被声明,当您设置它时,您也为第一次 add()
调用设置了它。因此,在 [1,2,3]
的每个元素调用 returnStorage
(第二个)10 毫秒后,[4,5,6,7]
的下一个元素将触发 returnStorage
回调,任何进一步的调用也将触发它。
我希望这个问题不是重复的,我在这里搜索过类似的问题但没有找到匹配的结果。
In node.js 下面的代码污染了 storage
变量。我真的想不通为什么。
var _ = require('underscore'); // same result by using lodash
function add(arr, callback) {
var l = arr.length,
storage = [];
function doCallback() {
callback(storage);
}
returnStorage = _.after(l, doCallback);
_.each(arr, function (a) {
_.delay(function () {
storage.push(a);
returnStorage();
}, 10);
});
}
function callbackHandler(result) {
console.log(result);
}
add([1,2,3], callbackHandler),
add([4,5,6,7], callbackHandler);
// in console will print wrong result:
// [ 4 ]
// [ 4, 5 ]
// [ 4, 5, 6 ]
// [ 4, 5, 6, 7 ]
但是,如果我不使用 _.after()
,它将给出预期的结果。使用 underscore 或 lodash 得到相同的结果。
下面的代码工作正常。
var _ = require('underscore'); // same result by using lodash
function add(arr, callback) {
var l = arr.length,
storage = [];
function returnStorage() {
if (storage.length == l) {
callback(storage);
}
}
_.each(arr, function (a) {
_.delay(function () {
storage.push(a);
returnStorage();
}, 10);
});
}
function callbackHandler(result) {
console.log(result);
}
add([1,2,3], callbackHandler),
add([4,5,6,7], callbackHandler);
// in console will print correct result:
// [ 1, 2, 3 ]
// [ 4, 5, 6, 7 ]
我应该如何确定根本原因!
javascript 上下文的魔力。当你在做的时候:
returnStorage = _.after(l, doCallback);
returnStorage
与您第二次调用 add
相同。
您需要用 var
声明它,使其成为函数的新函数和本地函数。
var _ = require('underscore'); // same result by using lodash
function add(arr, callback) {
var l = arr.length,
storage = [];
function doCallback() {
callback(storage);
}
var returnStorage = _.after(l, doCallback);
_.each(arr, function (a) {
_.delay(function () {
storage.push(a);
returnStorage();
}, 10);
});
}
function callbackHandler(result) {
console.log(result);
}
add([1,2,3], callbackHandler),
add([4,5,6,7], callbackHandler);
// in console:
// [ 1, 2, 3 ]
// [ 4, 5, 6, 7 ]
一点解释:
在您第一次调用 add()
时,returnStorage
是 undefined
。然后它将被定义为全局上下文,因为它们之前没有 var
。
在第二次调用时,变量被声明,当您设置它时,您也为第一次 add()
调用设置了它。因此,在 [1,2,3]
的每个元素调用 returnStorage
(第二个)10 毫秒后,[4,5,6,7]
的下一个元素将触发 returnStorage
回调,任何进一步的调用也将触发它。