为什么setTimeout是同步作用的?

Why is setTimeout acting synchronously?

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 looptask queue,在观看了一个很好的推荐视频 (https://www.youtube.com/watch?v=8aGhZQkoFbQ) 之后,我发现了以下半语句:"Callbacks can be synchronous and asynchronous".演讲者继续演示同步方式如何不会最终通过 task queue,因此不会通过 event loop,所以一切都保留在 stack 上。但是,异步方式会导致 task queuesetTimeout callback 的最终 return 填充,这将使自 [=16] 以来的任何同步代码都可执行=] 必须等待空 stack 才能插入 returned callback.

当运行上面的代码(我从他那里偷来的,也编辑过的,所以可能是我的错误添加),异步方式产生与同步方式相同的结果。

谁能帮忙解释一下为什么异步方式不能作为第一个 setTimeout 示例 and/or 提供有关如何不将常规回调(例如数组辅助方法)插入到task queue 因此永远不会被 event loop?

搞砸

您的 "asynchronous way" 不是异步的,因为您调用了该函数并将其 return 值传递给 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');

您的 asyncForEach 函数中存在错误。您立即调用 callBack(x),然后将该函数 (undefined) 的结果传递给 setTimeout.