节点异步数组循环结果不如预期

时间:2017-01-16 06:37:28

标签: javascript node.js callback event-loop



function asyncForEach(array,cb) {
    array.forEach(function(i){
        setTimeout(cb(i),0);
    });
}
asyncForEach([1,2,3,4], function(i) {
    console.log(i);
});

console.log("After loop");




您将看到的上述代码段的结果是

1
2
3
4
After loop

我的期望

After loop
1
2
3
4

我认为会发生的是函数asyncForEach将被添加到调用堆栈中,并且对于数组中的每个元素,setTimeout中的回调将被推送到回调队列。 Console.log(" After loop");将被打印,然后调用堆栈将变为空,之后所有回调将逐个执行。但事实似乎并非如此。谁能解释一下?

感谢。

2 个答案:

答案 0 :(得分:2)

问题是您手动调用forEach中的回调并将其结果传递给setTimeout。

setTimeout(cb(i), 0); // <-- you call cb(i) and pass its result into setTimeout

你想做的是:

setTimeout(cb, 0, i);

或更明确地说:

setTimeout(function() {
  cb(i);
}, 0);

完整示例:

&#13;
&#13;
function asyncForEach(array,cb) {
    array.forEach(function(i){
        setTimeout(cb, 0, i);
    });
}
asyncForEach([1,2,3,4], function(i) {
    console.log(i);
});

console.log("After loop");
&#13;
&#13;
&#13;

答案 1 :(得分:0)

要获得预期的输出,您需要进行以下更改:

function asyncForEach(array,cb) {
    array.forEach(function(i){
        setTimeout(function(){cb(i)},0); // CHANGE IS HERE
    });
}
asyncForEach([1,2,3,4], function(i) {
    console.log(i);
});
console.log("After loop");

基本上当你在setTimeout函数中提供函数调用(没有括号)时,你实际上是在调用该函数。 要在给定超时后调度函数调用,您必须在setTimeout方法中提供函数,就像我在上面的示例中提供的那样。