节点asynchronous数组循环结果不符合预期
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中的callback将被推送到callback队列。 Console.log(“After循环”); 将会被打印出来,然后调用堆栈将被清空,接下来所有的callback将被逐一执行。 但似乎并非如此。 谁能解释一下?
谢谢。
问题是你正在手动调用forEach中的callback,并将结果传递给setTimeout。
setTimeout(cb(i), 0); // <-- you call cb(i) and pass its result into setTimeout
你想要做的是这样的:
setTimeout(cb, 0, i);
或者更明确地说:
setTimeout(function() { cb(i); }, 0);
完整的例子:
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");
要获得预期的输出,您需要进行以下更改:
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
方法中提供函数,就像我在上面的例子中提供的那样。