JavaScript 一次只做一件事
主线程执行同步代码时,函数会依次进入调用栈。只有栈清空后,浏览器才有机会处理队列中的异步回调。
console.log('A');
setTimeout(() => console.log('B'), 0);
Promise.resolve().then(() => console.log('C'));
console.log('D');
// A → D → C → B微任务为什么更早执行
Promise 回调进入微任务队列,而定时器回调进入任务队列。当前脚本结束后,浏览器会先清空所有微任务,再进入下一个任务,因此 C 会早于 B 输出。
需要警惕的是,连续创建微任务可能让浏览器迟迟无法进入下一轮事件循环,从而阻塞用户输入和页面渲染。
渲染发生在哪里
浏览器通常会在任务之间寻找渲染机会。requestAnimationFrame 的回调在下一次绘制前运行,适合执行与视觉更新直接相关的工作。
理解事件循环的重点不是背输出顺序,而是知道何时把主线程还给浏览器。
面对大计算,可以拆分任务、使用 Web Worker,或通过调度 API 降低优先级。流畅体验的核心,是避免长时间独占主线程。