跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

HTML面试题事件循环_html面试题Event Loop事件循环【最全】

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

相关文章