Promise比setTimeout先执行,因为微任务队列会在当前宏任务结束后立即被清空,而setTimeout回调属于宏任务,必须等待所有微任务执行完毕后才进入下一轮事件循环。
直接说结论:事件循环不是“等 setTimeout 执行完再跑 Promise”,而是每次宏任务结束后,**立刻清空整个微任务队列**,之后才取下一个宏任务;这个“立刻清空”是关键,也是绝大多数面试题出错的根源。
为什么 console.log(1)、Promise.then、setTimeout(0) 输出顺序不是 1→2→3?
因为执行顺序不由“谁写在前面”决定,而由任务类型和事件循环阶段控制:
是同步代码,立即执行
的回调被推入**当前事件循环的微任务队列**,主线程一空就执行(不等下一个 tick)
的回调被推入**下一个事件循环的宏任务队列**,必须等当前宏任务 + 所有微任务全部跑完才轮到它
所以哪怕 delay 是 0,
也永远排在
后面——这不是“延迟不够”,而是规范定义的调度层级。
Promise 构造函数里的 resolve() 是同步还是异步?
构造函数体内的代码(包括
调用)是**同步执行**的,但
回调一定是微任务。
立即学习
“
前端免费学习笔记(深入)
”;
常见误判点:
使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
下载
写
→ 输出 a、b 立刻出现,说明构造函数同步运行
但
不会紧跟着 b 输出,它要等到当前调用栈清空、微任务队列开始执行时才触发
如果 resolve 传的是一个 pending Promise(比如
),那 .then 仍进微任务队列,但实际执行时机可能受嵌套 Promise 影响
async/await 本质就是 Promise 微任务,但容易漏掉隐式 await
函数返回值总是 Promise,
后面的表达式一旦不是 Promise,会被自动包装成
,然后其后续代码被注册为微任务。
典型陷阱:
→ 输出 1、2 是连续的,但“2”不是同步输出,它在微任务中执行
如果
被调用后,紧接着有
,那么“2”和“3”的顺序不确定:取决于 JS 引擎是否把 await 后续代码和这个
放进同一个微任务队列(Chrome 有时会合并,但规范不要求)
更危险的是
:这里产生了两层微任务,第二层会在第一层执行完后才入队,导致额外延迟
浏览器和 Node.js 的事件循环差异不能靠记忆,得看阶段名
浏览器 Event Loop 没有明确阶段划分,只按“宏任务 → 清空微任务 → 渲染(可选)→ 下一个宏任务”循环;Node.js(v11+)则严格分 6 个阶段,其中
和
都在 **microtask queue**,但它在每个阶段结束后都执行,比浏览器更激进。
真正影响实操的点:
Node.js 中
优先级高于
,即使写在后面也会先执行
浏览器里没有
,别在前端代码里用
写跨平台工具库时,避免依赖
或特定阶段行为,统一用
更安全
最常被忽略的其实是渲染时机:微任务清空后,浏览器会检查是否需要重绘。这意味着如果你在微任务里疯狂改 DOM,不会立刻触发多次 layout,但一次微任务链太长,会阻塞渲染——这比 setTimeout 延迟更隐蔽。
console.log(1)Promise.resolve().then(...)setTimeout(..., 0)setTimeoutPromise.thenresolve().then()new Promise(resolve => { console.log('a'); resolve(); console.log('b'); }).then(() => console.log('c'))resolve(Promise.resolve(42))asyncawaitPromise.resolve(value)async function f() { console.log('1'); await 2; console.log('2'); }f()Promise.resolve().then(() => console.log('3'))thenawait Promise.resolve().then(...)process.nextTick()Promise.then()process.nextTick()Promise.then()process.nextTick()nextTickqueueMicrotask()