JavaScript事件循环只调度已入队的回调,异步逻辑由宿主API执行;宏任务由宿主插入宏队列,微任务在当前任务后集中清空;Promise构造器同步执行,.then等为微任务;await等价于.then链;process.nextTick在Node.js中优先级高于微任务。

JavaScript事件循环不“执行”异步代码,它只按顺序调度和运行已进入任务队列的回调——真正执行异步逻辑的是浏览器或Node.js的底层API(如setTimeout、fetch、Promise构造器内部的同步部分)。
宏任务和微任务的排队时机不同
宏任务(如setTimeout、setInterval、I/O、UI渲染)由宿主环境插入宏任务队列;微任务(如Promise.then、MutationObserver、queueMicrotask)在当前任务结束后、下一个宏任务开始前集中清空。
-
Promise构造器里的函数是同步执行的,只有.then、.catch注册的回调才是微任务 -
setTimeout(() => {}, 0)不会立刻执行,它至少要等完当前调用栈 + 所有微任务 - 连续调用
queueMicrotask会累积到同一轮微任务队列,不会触发多次事件循环迭代
Promise链的每个.then都生成新微任务
哪怕写成promise.then(a).then(b).then(c),a、b、c也不是一次推入,而是a执行完后才把b推入微任务队列,b执行完再推c。这决定了错误传播和时序不可跳过中间环节。
- 如果
a抛错且没被.catch捕获,b会被跳过,c也不会执行 -
await本质上就是语法糖,等价于.then链,同样受微任务排队规则约束 - 不要指望
await Promise.resolve()比return快——它多了一次微任务调度,实际更慢
Node.js与浏览器的process.nextTick优先级更高
在Node.js中,process.nextTick的回调在当前操作完成后立即执行,甚至早于微任务队列——它不属于标准事件循环规范,是Node.js特有机制,常被库用于紧急响应(如避免error事件丢失)。
立即学习“Java免费学习笔记(深入)”;
- 浏览器没有
process.nextTick,用queueMicrotask最接近其语义 - 过度使用
process.nextTick可能导致I/O饥饿,因为它的回调会不断插队 -
Promise.resolve().then()和queueMicrotask在浏览器中行为一致,但后者无兼容性风险(IE不支持Promise,但queueMicrotask也需Chrome 68+/Firefox 69+
事件循环本身没有“并发”或“并行”能力,所有回调都是单线程串行执行的;所谓“异步”,只是把一部分工作移交给了宿主环境,并约定好什么时候把回调塞进哪个队列——真正容易被忽略的,是那些看似同步却偷偷触发异步分支的操作,比如new Promise(resolve => { resolve(); })立刻产生微任务,而resolve()调用本身却是同步的。










