for循环值中的NodeJS回调是相同的

时间:2016-04-18 19:59:23

标签: javascript node.js callback

我正在清理我的代码并遇到回调问题,特别是在调用回调时输出正确的值。有些解释对我来说为什么下面的代码会吐出一些我不期望的东西和一个可能的解决方案,而不必将其他参数i放入run()函数,或者传入i在调用回调时知道我的索引是唯一的方法吗?

for (var i in dls) {
    run(dls[i][0], dls[i][1], function(isTrue){
        if (isTrue) {
            // Do true stuff here
        } else {
            console.log("Value is: " + dls[i][3])
        }
    });
}

调用run()实际上内部有正确的输入,但是在调用回调并进入else语句的函数后,dls [i] [3]会出现相同的值i次。

我已尝试将不同的范围放在(run())等但是无济于事,似乎无法绕过这个。

谢谢

修改

如果我想把它拆分成一个单独的函数,我该怎么做?

var run = function(cb){
    setTimeout(function() {
        cb(false)
    }, 3000);
}

for (var i in dls) {
    run(dls[i][0], dls[i][1], (function(index) {
        return extraction
    })(i));
}

function extraction(isTrue){
    if (isTrue) {
        // stuff
    } else {
        console.log("Nothing changed in " + dls[i][3])
    }
}

这里dls [i] [3]仍然不正确并且打印相同的值3次。

2 个答案:

答案 0 :(得分:2)

你已陷入传统的“循环陷阱”

当您的回调运行i时,现在是一个不同的值。

您可以做的是将该值缓存在另一个包装函数中:

for (var i in dls) {
    run(dls[i][0], dls[i][1], (function (currentIndex) { 
        return function(isTrue){
            if (isTrue) {
                // Do true stuff here
            } else {
                console.log("Value is: " + dls[currentIndex][3])
            }
        };
    })(i));
}

答案 1 :(得分:1)

关于编辑/第二个问题,假设这是你想要做的:

// note that I changed the function signature of `run`
var run = function(val1, val2, cb) {
    setTimeout(function() {
        cb(false);
    }, 3000);
};

// note the `wrapper` here
for (var i in dls) {
    run(dls[i][0], dls[i][1], wrapper(i));
}

// this is the same as what the IIFE is doing,
// just with an external function instead
function wrapper(scopedIndex) {

    // return a function to be used as the callback for `run`
    return function extraction(isTrue) {
        if (isTrue) {
            // stuff
        }
        else {
            // use the scoped index here
            console.log("Nothing changed in " + dls[scopedIndex][3]);
        }
    }
}

另请查看其他linked question中的function makeExitCallback(i)。它直接关系到这里发生的事情。

您也应该在dls中发布内容,以便更轻松地在本地运行您的代码段。