JavaScriptの非同期処理をレストランで例えてみる

# JavaScriptの非同期処理をレストランに例えて理解しよう！

JavaScriptの非同期処理とイベントループは初心者にとって理解が難しい概念です。この記事では、**レストラン**という身近な例えを使って、JavaScriptの実行モデルをわかりやすく解説します。

![ChatGPT Image 2025年5月14日 08_45_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116912/1264feb6-994f-4386-8801-a3765e67f10e.png)


## 🍽️ JavaScriptの実行モデルをレストランにたとえる

| 用語 | レストランの役割 | JavaScriptの役割 |
|-----|--------------|--------------|
| メインスレッド | 席に座っているお客様（現在対応中） | **今実行中のタスク**（関数や処理が走っている状態） |
| タスクキュー | 順番待ちのお客様（料理が来るのを待っている） | **非同期処理の結果待ち**（setTimeoutやイベント） |
| イベントループ | シェフ（空いた席がないかを確認し料理を運ぶ） | **メインスレッドが空いたかを確認し、次の処理を実行** |

## 📝 具体例：レストランでの流れ

### 💡 シチュエーション

1. **お客様（メインスレッド）が席に座って食事中**
   * 他の客（非同期処理）は順番待ち（タスクキュー）
2. **順番待ちのお客様（非同期処理）が「デザート（setTimeout）」を注文**
   * シェフ（イベントループ）は「**3分後に出します**」と仮予約
   * デザートができても、**テーブルが空いてないと出せない**
3. **食事中のお客様（メインスレッド）が長々と食事を続ける（ブロッキング処理）**
   * デザートが出来上がっても、**席が空くまで運べない**
4. **やっと席が空いた（メインスレッドが解放された）**
   * シェフ（イベントループ）が**デザート（非同期タスク）**を運ぶ

## 📝 JavaScriptでの動きに置き換える

### **コード**

```javascript
console.log("Start");

setTimeout(() => {
  console.log("Dessert served");
}, 3000); // 3秒後に実行予約

const startTime = new Date();
while (new Date() - startTime < 5000); // 5秒間の食事（ブロッキング）

console.log("Main course done");
```

### **実行結果**

```
Start
Main course done
Dessert served
```

## 🍰 解釈

1. **Startを出力**
   * 最初のお客様が席に座り、**メインディッシュを食べ始めた**。
2. **setTimeoutで「3秒後にデザートを出す」とシェフが予約**
   * **デザート注文がタスクキューに入る**が、まだ**運ばれない**。
3. **5秒間のブロッキング（食事中）**
   * お客様が**メインディッシュを食べ続けている**ため、**シェフがデザートを出すタイミングを逃す**。
4. **食事が終わり席が空いた（メインスレッドが解放）**
   * シェフが**順番待ちのデザートをすぐに運ぶ**。

## 🔍 イベントループの流れを図解

```
  ┌─────────────────────┐
  │     メインスレッド     │
  │  (現在席に座っている人) │
  └──────────┬──────────┘
             │
             │ 完了
             ▼
  ┌─────────────────────┐      ┌─────────────────────┐
  │    イベントループ     │ 次へ │     タスクキュー       │
  │  (席が空いたか確認)   │◄─────┤ (デザート提供待ち)     │
  └──────────┬──────────┘      └─────────────────────┘
             │
             │ 空席確認
             ▼
 ┌─────────────────────────┐
 │メインスレッドが空いている？│
 └────────────┬────────────┘
              │
    ┌─────────┴─────────┐
    │                   │
    ▼                   ▼
【はい】席が空いた      【いいえ】まだ食事中
    │                   │
  ▼                     │
次のタスクを実行           │
   │                    │
   └────────────────────┘
```

## 🍽️ よりわかりやすくするポイント

### **「テーブルが空かないと料理が出せない」**
* **メインスレッドが空かないと、非同期処理が実行されない**。
* **デザートが出来ても、テーブルが塞がっていれば運べない**。

### **「料理を運ぶのはシェフ」**
* シェフ（イベントループ）は、**メインスレッドが空いたかを確認**して、空いたら**次の料理を運ぶ**。
* シェフ自体が料理を作るわけではなく、**タイミング管理が仕事**。

### **「非同期処理は予約しているだけ」**
* **デザートを頼んだからといって、すぐに出てくるわけではない**。
* **予約が通っても、実際に提供されるのは席が空いてから**。

## 💡 このたとえで覚えるポイント

1. **メインスレッド**（席に座っているお客様）が**食事をしている間**は、他の料理が**出せない**。
2. **タスクキュー**（順番待ちの料理）は、**メインスレッドが空いたとき**に**順番に提供される**。
3. **イベントループ**（シェフ）は、**メインスレッドが空いたかを常に監視**し、空いた瞬間に**次のタスクを持ってくる**。
4. **非同期処理**（デザートの予約）は、**後で実行するという「約束」**であり、**予約が成立してもすぐには実行されない**。

## 🚀 補足：もしメインスレッドが常に埋まっていたら？

* **ずっと席に座り続ける客（whileループでブロッキング）**がいると、**予約していた料理が出せない**。
* **結果として、デザートが溜まってしまい、提供が遅れる**。
* **席が空いた瞬間にまとめて運ばれる**が、注文タイミングが遅くなってしまう。

## ✅ まとめ

* **メインスレッド＝現在の仕事中のお客様**：終わらない限り他の処理はできない
* **タスクキュー＝次に実行したい非同期処理の待機列**：メインスレッドが空くのを待っている
* **イベントループ＝シェフ**：メインスレッドが空いたときに次のタスクを実行
* **非同期処理＝予約**：実行タイミングが来ても、**席が空いていないと実行できない**

## 👨‍💻 実際に確認してみよう

以下のコードを実行して、実際の動きを確認してみましょう：

```javascript
console.log("🍽️ お客様が入店しました");

// メインコースの注文
console.log("🍖 メインコースを注文しました");

// デザートを3秒後に予約
setTimeout(() => {
  console.log("🍰 デザートが提供されました");
}, 3000);

// 5秒かかるメインコース（ブロッキング処理）
console.log("🕒 メインコースを食べています...");
const startTime = new Date();
while (new Date() - startTime < 5000);

console.log("✅ メインコースを食べ終わりました");

// 結果:
// 🍽️ お客様が入店しました
// 🍖 メインコースを注文しました
// 🕒 メインコースを食べています...
// ✅ メインコースを食べ終わりました
// 🍰 デザートが提供されました
```

この例では、3秒後にデザートを出す予約をしましたが、メインコースに5秒かかったため、デザートはメインコースが終わった後に提供されました。これがJavaScriptの非同期処理の基本的な流れです！