在异步回调中使用_.after(),污染数组变量

时间:2015-12-17 10:34:16

标签: javascript node.js underscore.js lodash

我希望这个问题不重复,我在这里搜索过类似的问题,但没有得到匹配的结果。

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(),它将给出预期的结果。使用下划线 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 ]

我应该如何确定根本原因!

1 个答案:

答案 0 :(得分:2)

javascript环境的神奇之处。当你这样做时:

returnStorage = _.after(l, doCallback);
{p> 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()时,returnStorageundefined。然后将它定义为全局上下文,因为它们之前不是var

在第二次调用时,声明变量,当你设置它时,你也可以为第一个add()调用设置它。因此,在10毫秒后[1,2,3]的每个元素调用returnStorage(第二个),[4,5,6,7]的下一个元素将触发returnStorage回调,任何进一步的调用也会触发它