1.实验
我们来做个实验。哪个执行得更快:立即解决的 Promise 还是立即setTimeout(也就是 0 毫秒的 setTimeout)?
Promise.resolve(1).then(function resolve() {
console.log('Resolved!');
});
setTimeout(function timeout() {
console.log('Timed out!');
}, 0);
// 'Resolved!'
// 'Timed out!'
promise.resolve(1)是一个静态函数,它返回一个立即解析的promise。setTimeout(callback, 0)以0 毫秒的延迟执行回调函数。
我们可以看到先打印'Resolved!',再打印Timeout completed!,立即解决的 promise 比立即setTimeout更快。
是因为Promise.resolve(true).then(...)在setTimeout(..., 0)之前被调用了,所以 Promise 过程会更快吗? 公平的问题。
所以,我们稍微更改一下实验条件,然后先调用setTimeout(..., 0):
setTimeout(function timeout() {
console.log('Timed out!');
}, 0);
Promise.resolve(1).then(function resolve() {
console.log('Resolved!');
});
// 'Resolved!'
// 'Timed out!'
setTimeout(..., 0)在Promise.resolve(true).then(...)之前被调用。但,还是先打印Resolved!在打印'Timed out!'。
这是为啥呢?
2.事件循环
与异步 JS 相关的问题可以通过研究事件循环来回答。我们回顾一下异步 JS 工作方式的主要组成部分。

调用堆栈为空,已完成脚本的执行。
总结
为什么立即解决的 promise 比立即执行定时器setTimeout()处理得更快?
由于事件循环优先级的存在,因此与任务队列(存储超时的setTimeout()回调)相比,作业队列(用于存储已实现的Promise回调)的优先级更高。