導入: なぜMacrotask queueを知る必要があるのか
JavaScriptは「シングルスレッド」で動作する言語です。つまり、一度に一つのタスクしか実行できません。しかし、通信やタイマー処理といった「時間がかかる処理」をメインの実行フローで待機させてしまうと、画面がフリーズしてしまいます。この課題を解決するのが「非同期処理」であり、その背後でタスクを管理しているのがMacrotask queue(マクロタスクキュー)です。この仕組みを理解することは、処理の順番によるバグを防ぎ、パフォーマンスを最適化するために不可欠です。
基礎知識: イベントループとタスクの正体
JavaScriptの実行環境には「コールスタック」「Web APIs」「タスクキュー(Macrotask queue)」という仕組みがあります。
プログラムが実行される際、同期処理はコールスタックで即座に処理されます。一方で、setTimeoutやsetIntervalなどの非同期処理は、一度Web APIsに渡され、タイマー完了後にMacrotask queueへと送られます。
「イベントループ」は、コールスタックが空になったタイミングで、このキューに溜まったタスクを一つずつ取り出し、実行するという役割を担っています。
実装/解決策: マクロタスクの実行順序を制御する
マクロタスクはキュー(先入れ先出し)の原則に従います。重要なのは、ブラウザは「一つのマクロタスクを実行するたびに、必要に応じてレンダリング(描画)を更新する」という点です。したがって、重たい処理を一つのタスクに詰め込むと画面が固まり、複数の小さなタスクに分けるとユーザーの操作性が向上します。
サンプルプログラム: マクロタスクの挙動を確認する
以下のコードを実行して、コンソールログの順序を確認してみてください。
console.log('1. 同期処理の開始');
// setTimeoutはマクロタスクとしてキューに追加されます
setTimeout(() => {
console.log('3. マクロタスク(setTimeout)の実行');
}, 0);
// Promiseはマイクロタスク(マクロタスクより優先される)として扱われます
Promise.resolve().then(() => {
console.log('2. マイクロタスク(Promise)の実行');
});
console.log('1. 同期処理の終了');
/
実行結果の順序:
1. 同期処理の開始
2. 同期処理の終了
3. 2. マイクロタスク(Promise)の実行
4. 3. マクロタスク(setTimeout)の実行
/
応用・注意点: 現場で役立つ開発のポイント
現場で注意すべき点は、「マイクロタスク(Promiseなど)はマクロタスクより優先される」という仕様です。Promiseを多用すると、マクロタスクであるsetTimeoutの実行が期待よりも遅延することがあります。
また、ブラウザの描画をスムーズに保つためには、一度のループで重い計算をさせず、`setTimeout` を使ってタスクを細切れに分割する手法(タイムスライシング)が有効です。これにより、ユーザーは処理中でもボタンのクリックやスクロールといった操作を快適に行えるようになります。複雑な非同期処理を行う際は、常に「どのタスクがいつ実行されるか」を意識して設計しましょう。