我终于彻底搞懂了 Promise:从「看了无数教程」到「真正理解异步」

这两年我看过市面上几乎所有 Promise 教程,但始终是一知半解。直到我搞清楚了浏览器多线程、事件循环和微任务,才迎来真正的顿悟。 前言:那些年我踩过的坑 Promise 的重要性不言而喻,可就是学不会。我看过阮一峰老师的教程,刷过各种视频,甚至能背出"链式调用、解决回调地狱"这些概念,但一碰到执行顺序的题目就懵。 最大的误解是什么?我以前一直以为"异步"就是 JS单线程同时处理多件事情,好像它能一边倒计时一边执行下面的代码。这种错误认知让我在面对 setTimeout 和 Promise 混用的代码时永远答不对。 直到我读了一篇文章 —— 《从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理》,配合阮一峰的 Promise 教程重新学习,我才真正开了窍。 下面我把这次"顿悟"的过程完整梳理出来,希望能帮助那些和我一样曾经痛苦挣扎的同学。 一、核心突破:理解"单线程异步"的真正含义 误解 vs 真相 我曾经的误解 真正的机制 JS 自己一边倒计时一边执行后面的代码 JS 把定时任务交给浏览器的定时器线程去处理 异步就是单线程来回切换干不同的事 异步是发布订阅模式:订阅事件 → 别的线程执行 → 完成后把回调放回任务队列 Promise 构造函数里的代码也是异步的 Promise 构造函数内的代码同步执行,只有 .then 回调才是微任务 核心记忆:JavaScript 引擎是单线程的,但浏览器是多线程的。 当 JS 遇到 setTimeout(cb, 1000) 时,它不会自己倒计时。它会说:“定时器线程,请你在 1 秒后把这个 cb 函数放回任务队列。“然后自己立刻继续执行后续同步代码。定时器线程倒计时结束后,把 cb 塞进宏任务队列,等待主线程空闲时通过事件循环(Event Loop)取走执行。 这就是你理解的 “Promise 中去使用 event loop 以外的线程,然后发布订阅模式” —— 完全正确。 二、事件循环(Event Loop)与任务队列 一旦理解了上面的外包机制,事件循环就变得非常直观。 1. 两类任务 宏任务(MacroTask):整体 script 代码、setTimeout、setInterval、I/O、UI 渲染。 微任务(MicroTask):Promise.then()、Promise.catch()、MutationObserver。 2. Event Loop 执行顺序 执行一个宏任务(最开始就是整个 script 代码)。 执行过程中产生的所有微任务,放入微任务队列。 当前宏任务执行完毕后,立刻清空整个微任务队列。 进行必要的 UI 渲染。 从宏任务队列中取出下一个宏任务,循环往复。 关键点:微任务的优先级永远高于宏任务。先清空微任务,再取下一个宏任务。 ...

June 9, 2026 · 3 min · 472 words