阅读下面关于setTimeout和Promise的代码,判断结果会输出什么?为什么?

console.log('start');

setTimeout(() => {
  console.log('timeout');
}, 0);

Promise.resolve().then(() => {
  console.log('promise1');
}).then(() => {
  console.log('promise2');
});

console.log('end');

这段代码会输出:

start
end
promise1
promise2
timeout

原因如下:

  1. 事件循环 (Event Loop) 和任务队列 (Task Queue/Microtask Queue): JavaScript 是单线程的,它通过事件循环来处理异步操作。事件循环维护一个任务队列和一个微任务队列。宏任务 (Macrotask) 包括 setTimeoutsetIntervalXMLHttpRequestUI events 等。微任务 (Microtask) 包括 Promise.thenPromise.catchMutationObserverqueueMicrotask 等。

  2. 执行顺序:

    • 首先,console.log('start') 被执行,输出 start
    • 然后,setTimeout(() => { ... }, 0) 被调用。虽然定时器设置为 0,但这并不意味着它会立即执行。setTimeout 会将回调函数放入宏任务队列中,等待当前调用栈清空后,事件循环才会从宏任务队列中取出任务执行。
    • 接下来,Promise.resolve().then(() => { ... }) 被调用。Promise.resolve() 会创建一个立即 resolved 的 Promise,它的 then 回调会被放入微任务队列。
    • 之后,console.log('end') 被执行,输出 end
    • 至此,当前调用栈为空。事件循环开始检查微任务队列。由于微任务队列中有 promise1 的回调,所以先执行 console.log('promise1'),输出 promise1
    • promise1 的回调执行完毕后,promise2 的回调也被放入微任务队列,因此立即执行 console.log('promise2'),输出 promise2
    • 现在微任务队列为空,事件循环开始检查宏任务队列。由于宏任务队列中有 setTimeout 的回调,所以执行 console.log('timeout'),输出 timeout

总结: 尽管 setTimeout 的延迟时间设置为 0,但它仍然是一个宏任务,会在所有微任务执行完毕后才执行。因此,promise1promise2 会在 timeout 之前输出。

希望这个解释能够帮助你理解 JavaScript 的事件循环机制。

posted @   王铁柱6  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示