本文是个人阅读推荐,非原创。原文作者:腾讯云开发者社区
为什么推荐这篇文章
学 Promise、学 async/await、学事件循环——我相信大部分前端都经历过这个过程:看了无数教程,能背出"链式调用"“解决回调地狱"这些概念,但一碰到执行顺序的题目就懵。
问题出在哪?我们跳过了底层机制,直接去学上层 API。
这篇文章做了一件很多人没做过的事:从浏览器是多进程的这个事实出发,一路梳理到 JS 引擎的单线程本质,再到 Event Loop 的完整机制。 读完之后你会发现,Promise 的所有行为都变得合理且可预测,而不是需要死记硬背的"规则”。
文章讲了什么
大致脉络:
- 进程 vs 线程 —— 用工厂和工人的比喻讲清楚区别,不啰嗦
- 浏览器是多进程的 —— 每个 Tab 页是一个独立进程,Browser 进程、GPU 进程、渲染进程各司其职
- 浏览器内核(渲染进程)内部的线程关系 —— GUI 渲染线程与 JS 引擎线程互斥,这就是为什么 JS 会阻塞页面渲染
- JS 引擎的单线程本质 —— JS 引擎线程一次只能做一件事,但浏览器其他线程可以并行
- Event Loop 完整机制 —— 宏任务、微任务、任务队列,讲得非常透彻
- 定时器的真相 ——
setTimeout不是精确计时,而是交给浏览器定时器线程处理
最值得读的部分
我个人觉得最有价值的三个点:
① JS 引擎线程和 GUI 渲染线程互斥
这解释了为什么耗时的 JS 代码会导致页面卡顿——不是因为 JS “慢”,而是因为它们抢同一个线程,JS 执行时页面没法渲染。
② 异步的本质是"外包"
JS 遇到 setTimeout、网络请求等异步操作时,自己不会去做,而是交给浏览器的其他线程(定时器线程、网络线程等),完成后把回调函数放回任务队列,等主线程空闲时再执行。这就是发布订阅模式的实际应用。
③ 微任务优先级高于宏任务
每次执行完一个宏任务后,会先清空所有微任务(Promise.then 的回调),再去取下一个宏任务(setTimeout 的回调)。这一个规则就能解释 95% 的执行顺序问题。
适合谁读
- 用过 Promise 但说不清执行顺序的前端开发者
- 想真正理解
async/await为什么"看起来像同步"的人 - 面试被事件循环题虐过的朋友
- 任何想从"会用"进阶到"理解"的前端
⚠️ 原文较长,适合有一定基础的开发者。新手可以分批阅读,先理解进程/线程的概念,再看 Event Loop 部分。
原文链接
👉 从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理
推荐给和我一样曾经在异步编程中迷茫过的朋友。先把底层搞懂,上层的 API 自然就通了。