Skip to content

Node.js 宏任务与微任务快速参考卡

🚀 微任务 (Micro Tasks)

执行时机: 在每个事件循环阶段之间执行

优先级排序 (从高到低):

优先级API说明示例
最高process.nextTick()Node.js特有,最高优先级process.nextTick(() => {})
Promise.then()Promise成功回调Promise.resolve().then(() => {})
Promise.catch()Promise失败回调Promise.reject().catch(() => {})
Promise.finally()Promise完成回调Promise.resolve().finally(() => {})
async/awaitPromise语法糖await Promise.resolve()
queueMicrotask()通用微任务APIqueueMicrotask(() => {})

⏰ 宏任务 (Macro Tasks)

执行时机: 按事件循环的6个阶段顺序执行

Timer 阶段

API说明示例
setTimeout()延时执行setTimeout(() => {}, 1000)
setInterval()间隔执行setInterval(() => {}, 1000)
clearTimeout()清除延时器clearTimeout(timerId)
clearInterval()清除间隔器clearInterval(intervalId)

Poll 阶段 (I/O操作)

分类API说明示例
文件系统fs.readFile()读取文件fs.readFile('file.txt', callback)
文件系统fs.writeFile()写入文件fs.writeFile('file.txt', data, callback)
文件系统fs.stat()文件状态fs.stat('file.txt', callback)
文件系统fs.readdir()读取目录fs.readdir('./', callback)
文件系统fs.mkdir()创建目录fs.mkdir('dir', callback)
文件系统fs.unlink()删除文件fs.unlink('file.txt', callback)
网络http.request()HTTP请求http.request(options, callback)
网络http.get()HTTP GEThttp.get(url, callback)
网络https.request()HTTPS请求https.request(options, callback)
DNSdns.lookup()DNS查询dns.lookup('google.com', callback)
DNSdns.resolve()DNS解析dns.resolve('google.com', callback)
TCPnet.connect()TCP连接net.connect(port, host, callback)
stream.read()流读取stream.on('data', callback)
加密crypto.pbkdf2()密码派生crypto.pbkdf2(password, salt, iterations, keylen, digest, callback)
压缩zlib.gzip()Gzip压缩zlib.gzip(buffer, callback)

Check 阶段

API说明示例
setImmediate()立即执行setImmediate(() => {})
clearImmediate()清除立即执行clearImmediate(immediateId)

Close 阶段

API说明示例
socket.on('close')Socket关闭socket.on('close', callback)
server.on('close')服务器关闭server.on('close', callback)
process.on('exit')进程退出process.on('exit', callback)

📊 执行顺序总结

1. 同步代码 (立即执行)

2. 微任务队列
   - process.nextTick (最高优先级)
   - Promise.then/catch/finally
   - queueMicrotask

3. 宏任务 (按事件循环阶段)
   - Timer阶段: setTimeout, setInterval
   - Poll阶段: I/O操作回调
   - Check阶段: setImmediate
   - Close阶段: 关闭事件回调

4. 重复步骤2-3,直到所有任务完成

⚠️ 特殊情况

I/O回调中的执行顺序

javascript
fs.readFile('file.txt', () => {
    setTimeout(() => console.log('setTimeout'), 0);     // 后执行
    setImmediate(() => console.log('setImmediate'));   // 先执行
});

微任务的嵌套

javascript
process.nextTick(() => {
    console.log('nextTick 1');
    process.nextTick(() => console.log('nextTick 2')); // 会在同一轮执行
});

💡 最佳实践

✅ 推荐做法

  • 优先使用 Promise 而不是 process.nextTick
  • 使用 setImmediate 而不是 setTimeout(fn, 0)
  • 避免在微任务中执行CPU密集型操作
  • 合理控制微任务数量,防止阻塞事件循环

❌ 避免的做法

javascript
// 危险:无限递归微任务
function badRecursion() {
    process.nextTick(badRecursion); // 会阻塞事件循环
}

// 安全:使用宏任务
function goodRecursion() {
    setImmediate(goodRecursion); // 不会阻塞事件循环
}

🔍 调试技巧

查看执行顺序

javascript
console.trace('当前调用栈');
process.nextTick(() => console.trace('nextTick'));
Promise.resolve().then(() => console.trace('Promise'));
setTimeout(() => console.trace('setTimeout'), 0);

监控事件循环延迟

javascript
const { performance } = require('perf_hooks');

function checkEventLoopDelay() {
    const start = performance.now();
    setImmediate(() => {
        const delay = performance.now() - start;
        console.log(`事件循环延迟: ${delay.toFixed(2)}ms`);
    });
}

📈 性能对比

基于测试结果,性能排序(从快到慢):

  1. setImmediate - 最快的宏任务
  2. setTimeout - 中等性能的宏任务
  3. Promise.then - 最快的微任务
  4. process.nextTick - 较慢的微任务
  5. queueMicrotask - 最慢的微任务

记住: 微任务优先级高于宏任务,但过多的微任务会阻塞事件循环!