1. イベントループフェーズ
┌───────────────────────────┐
┌─>│ timers │ setTimeout, setInterval
│ └──────────┬────────────────┘
│ ┌──────────┴────────────────┐
│ │ pending callbacks │ I/O callbacks deferred
│ └──────────┬────────────────┘
│ ┌──────────┴────────────────┐
│ │ idle, prepare │ internal use
│ └──────────┬────────────────┘
│ ┌──────────┴────────────────┐
│ │ poll │ I/O events (fs, net)
│ └──────────┬────────────────┘
│ ┌──────────┴────────────────┐
│ │ check │ setImmediate
│ └──────────┬────────────────┘
│ ┌──────────┴────────────────┐
└──│ close callbacks │ socket.on('close')
└───────────────────────────┘
2. マイクロタスクとマクロタスク
console.log('1: Script start')
setTimeout(() => console.log('2: setTimeout'), 0) // Macrotask (timers)
setImmediate(() => console.log('3: setImmediate')) // Macrotask (check)
Promise.resolve().then(() => console.log('4: Promise')) // Microtask
queueMicrotask(() => console.log('5: queueMicrotask')) // Microtask
process.nextTick(() => console.log('6: nextTick')) // Microtask (ưu tiên cao nhất)
console.log('7: Script end')
// Output:
// 1: Script start
// 7: Script end
// 6: nextTick ← nextTick luôn chạy trước
// 4: Promise
// 5: queueMicrotask
// 2: setTimeout ← hoặc 3 trước (phụ thuộc event loop)
// 3: setImmediate
3. process.nextTick と queueMicrotask の比較
| API | キュー | 注文 | いつ使用するか |
|---|---|---|---|
| process.nextTick | 次のティックキュー | 最高 | 現在の操作の直後に必ず実行してください |
| キューマイクロタスク | マイクロタスクキュー | 次のティックの後 | 標準準拠、Web 互換 |
| 約束してください。それでは | マイクロタスクキュー | 次のティックの後 | 非同期チェーン |
| setTimeout(fn, 0) | タイマーフェーズ | マクロタスク | 次のイベントループの繰り返しまで延期する |
| セット即時 | チェックフェーズ | マクロタスク | I/Oポーリング後に実行 |
4. 非同期パターンの進化
import { readFile } from 'node:fs'
import { readFile as readFileAsync } from 'node:fs/promises'
// 1. Callback (old style)
readFile('/etc/hosts', 'utf8', (err, data) => {
if (err) throw err
console.log(data)
})
// 2. Promise
readFileAsync('/etc/hosts', 'utf8')
.then(data => console.log(data))
.catch(err => console.error(err))
// 3. Async/Await (recommended)
async function main() {
try {
const data = await readFileAsync('/etc/hosts', 'utf8')
console.log(data)
} catch (err) {
console.error(err)
}
}
5. Promise コンビネータ
const tasks = [
fetch('https://api.example.com/users'),
fetch('https://api.example.com/posts'),
fetch('https://api.example.com/comments'),
]
// Promise.all — fail nếu 1 reject
const [users, posts, comments] = await Promise.all(tasks)
// Promise.allSettled — không fail, trả status
const results = await Promise.allSettled(tasks)
results.forEach(r => {
if (r.status === 'fulfilled') console.log(r.value)
else console.error(r.reason)
})
// Promise.any — trả kết quả đầu tiên thành công
const fastest = await Promise.any(tasks)
// Promise.race — trả kết quả đầu tiên (fulfilled hoặc rejected)
const first = await Promise.race(tasks)
6. アボートコントローラー
const controller = new AbortController()
const { signal } = controller
// Timeout tự động cancel
setTimeout(() => controller.abort(), 5000)
try {
const response = await fetch('https://api.example.com/data', { signal })
const data = await response.json()
} catch (err) {
if (err instanceof DOMException && err.name === 'AbortError') {
console.log('Request was aborted')
}
}
次の記事: モジュールシステムとパッケージ管理 — CJS 対 ESM、npm、pnpm。