setTimeout
在下面的同步代码之后被执行的示例
console.log('hello');
setTimeout(() => console.log('timeout'), 0);
console.log('end');
控制台输出: 你好 结束 超时
异步:
function asyncForEach(array, callBack) {
array.forEach(x => setTimeout(callBack(x), 0));
}
asyncForEach([1,2,3,4], (i) => console.log(i));
console.log('end');
控制台输出:
1
2
3
4
end
同步:
[1,2,3,4].forEach(x => console.log(x));
console.log('end');
控制台输出:
1
2
3
4
end
我试图更好地理解event loop
和task queue
,并且在观看了值得推荐的视频(https://www.youtube.com/watch?v=8aGhZQkoFbQ)之后出现了以下半句:“回调可以是同步的,异步”。演讲者继续演示了同步方式如何最终不会通过task queue
,因此也不会通过event loop
,因此一切都保留在stack
上。但是,异步方式将导致task queue
setTimeout
的最终返回填充callback
,这将使任何下面的同步代码可执行,因为event loop
必须等待空的stack
插入返回的callback
。
运行上面的代码时(我从他那里偷走了东西,还进行了编辑,因此对我而言可能是错误的添加),异步方式产生的结果与同步方式相同。
有人可以帮助解释为什么异步方式不作为第一个setTimeout
示例的原因和/或提供有关如何不将常规回调(例如数组帮助器方法)插入{{1}的解释。 }因此从未被task queue
弄乱吗?
答案 0 :(得分:4)
您的“异步方式”不是异步的,因为您调用了该函数并将其返回值传递给setTimeout
:
function asyncForEach(array, callBack) {
array.forEach(x => setTimeout(callBack(x), 0)); // <-- callBack(x) calls callBack immediately
}
asyncForEach([1,2,3,4], (i) => console.log(i));
console.log('end');
如果您希望它延迟,则将一个函数传递给setTimeout
以便稍后调用:
function asyncForEach(array, callBack) {
array.forEach(x => setTimeout(() => callBack(x), 0)); // <-- Makes closure that calls callBack(x) later
}
asyncForEach([1,2,3,4], (i) => console.log(i));
console.log('end');
答案 1 :(得分:2)
您的asyncForEach
函数中存在错误。您正在立即调用callBack(x)
,然后将该函数(undefined
)的结果传递给setTimeout
。