# 機能設計書 29-nextTick()

## 概要

本ドキュメントは、Vue 3の`nextTick()`関数の機能設計を記述する。次のDOM更新サイクル（マイクロタスクフラッシュ）の完了後にコールバックを実行するためのユーティリティ関数であり、リアクティブデータ変更後のDOM状態にアクセスする際に使用される。

### 本機能の処理概要

`nextTick()`はVueの非同期更新キューの完了を待機するためのPromiseベースのAPIである。Vueはリアクティブデータの変更を即座にDOMに反映せず、マイクロタスクでバッチ処理する。`nextTick()`はこのバッチ処理の完了後にコールバックを実行する、またはawaitで待機することを可能にする。

**業務上の目的・背景**：Vueのリアクティブシステムはパフォーマンス最適化のためにDOM更新をバッチ処理する。そのため、リアクティブデータの変更直後にDOMを参照しても、まだ古い状態が残っている。`nextTick()`はDOM更新完了後の安全なDOMアクセスタイミングを提供し、DOM計測やサードパーティライブラリとの連携を可能にする。

**機能の利用シーン**：リアクティブデータ変更後のDOM要素のサイズ・位置計測、DOM更新後のスクロール位置調整、サードパーティDOMライブラリ（チャートライブラリ等）との連携、テストでのDOM更新待機。

**主要な処理内容**：
1. `nextTick(fn?)`の呼び出し
2. `currentFlushPromise`（現在のフラッシュ処理のPromise）が存在する場合はそれを使用、存在しない場合は`resolvedPromise`（即座に解決済みのPromise）を使用
3. fnが指定されている場合：Promiseの`.then(fn)`でコールバックをスケジュール
4. fnが未指定の場合：Promiseをそのまま返却（await可能）
5. thisバインディングが指定されている場合は`fn.bind(this)`で束縛

**関連システム・外部連携**：スケジューラ（`queueJob`、`flushJobs`）、`currentFlushPromise`（フラッシュ状態管理）、`resolvedPromise`（デフォルトPromise）と連携する。

**権限による制御**：権限による制御は存在しない。任意の場所から呼び出し可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに直接の関連画面なし。DOM更新後の処理が必要な全ての画面で潜在的に使用される |

## 機能種別

非同期スケジューリング / ユーティリティ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| fn | ((this: T) => R \| Promise\<R\>) | No | DOM更新後に実行するコールバック関数。省略時はPromiseのみ返却 | なし |

### 入力データソース

任意のコンテキストからのプログラム呼び出し。setup()内に限定されない。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| promise | Promise\<void \| R\> | DOM更新完了後に解決されるPromise。fnが指定されている場合はfnの戻り値で解決 |

### 出力先

呼び出し元への戻り値（Promise）。

## 処理フロー

### 処理シーケンス

```
1. nextTick(fn?) 呼び出し
   └─ const p = currentFlushPromise || resolvedPromise
2. fn が指定されている場合
   ├─ this が存在する場合：p.then(fn.bind(this))
   └─ this が存在しない場合：p.then(fn)
3. fn が未指定の場合
   └─ p をそのまま返却
4. 返却されたPromiseをawaitまたは.thenで使用
```

### フローチャート

```mermaid
flowchart TD
    A[nextTick fn?] --> B{currentFlushPromise存在?}
    B -->|Yes| C[p = currentFlushPromise]
    B -->|No| D[p = resolvedPromise]
    C --> E{fn指定あり?}
    D --> E
    E -->|Yes| F{this存在?}
    F -->|Yes| G[return p.then fn.bind this]
    F -->|No| H[return p.then fn]
    E -->|No| I[return p]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-29-01 | フラッシュPromise優先 | currentFlushPromise（現在のスケジューラフラッシュPromise）が存在する場合はそれを使用し、フラッシュ完了後にコールバックを実行する | currentFlushPromise !== null |
| BR-29-02 | 即時解決フォールバック | currentFlushPromiseが存在しない場合はresolvedPromise（即座に解決されるPromise）を使用し、次のマイクロタスクで実行する | currentFlushPromise === null |
| BR-29-03 | thisバインディング | this引数が指定されている場合はfn.bind(this)でコールバックにthisを束縛する | this指定時 |
| BR-29-04 | Promiseチェーン統合 | currentFlushPromiseはqueueFlush()内でresolvedPromise.then(flushJobs)により生成される | スケジューラ動作時 |

### 計算ロジック

該当なし。

## データベース操作仕様

### 操作別データベース影響一覧

該当なし（クライアントサイドフレームワーク機能）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Promise rejection | コールバック関数内で例外が発生した場合 | Promiseのcatchチェーンでハンドリング |

### リトライ仕様

リトライ機構は存在しない。

## トランザクション仕様

該当なし。

## パフォーマンス要件

- `nextTick()`自体は軽量な処理（Promise.then()のみ）
- `resolvedPromise`はモジュールレベルで1度だけ生成される（`Promise.resolve()`）
- DOM更新のバッチ処理によりパフォーマンスが最適化されている

## セキュリティ考慮事項

該当なし。

## 備考

- `nextTick()`はsetup()内に限定されず、任意のコンテキスト（イベントハンドラ、外部コード等）から呼び出し可能
- Vue 2では`Vue.nextTick()`としてグローバルAPIだったが、Vue 3では名前付きエクスポートとして提供される
- `resolvedPromise`は`/*@__PURE__*/ Promise.resolve()`でツリーシェイキング対応

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

スケジューラの内部状態変数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | scheduler.ts | `packages/runtime-core/src/scheduler.ts` | `resolvedPromise`（50行目）。`Promise.resolve()`で即座に解決されるPromise |
| 1-2 | scheduler.ts | `packages/runtime-core/src/scheduler.ts` | `currentFlushPromise`（51行目）。現在のスケジューラフラッシュ処理のPromise |

**読解のコツ**: `resolvedPromise`はモジュールスコープの定数で、`nextTick()`のデフォルトPromiseとして使用される。`currentFlushPromise`は`queueFlush()`内で`resolvedPromise.then(flushJobs)`により設定され、`flushJobs`完了後にnullにリセットされる。

#### Step 2: エントリーポイントを理解する

nextTick関数の定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | scheduler.ts | `packages/runtime-core/src/scheduler.ts` | nextTick関数（56-67行目）。2つのオーバーロードと1つの実装 |

**主要処理フロー**:
1. **56行目**: `nextTick(): Promise<void>` - 引数なしオーバーロード
2. **57-60行目**: `nextTick<T, R>(this: T, fn: (this: T) => R | Promise<R>): Promise<R>` - 関数指定オーバーロード
3. **61-67行目**: 実装。`const p = currentFlushPromise || resolvedPromise`でPromiseを取得し、fnがあれば`p.then(fn)`、なければ`p`を返却

#### Step 3: スケジューラとの関連を理解する

currentFlushPromiseがどのように設定・クリアされるかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | scheduler.ts | `packages/runtime-core/src/scheduler.ts` | queueFlush関数（119-123行目）。currentFlushPromise = resolvedPromise.then(flushJobs) |
| 3-2 | scheduler.ts | `packages/runtime-core/src/scheduler.ts` | flushJobs関数（214-268行目）。finally内でcurrentFlushPromise = null |

**主要処理フロー**:
- **119-123行目**: `queueFlush()`。`currentFlushPromise`が未設定の場合に`resolvedPromise.then(flushJobs)`を設定
- **262行目**: `flushJobs`のfinally内で`currentFlushPromise = null`にリセット

### プログラム呼び出し階層図

```
nextTick(fn?)
    │
    ├─ currentFlushPromise || resolvedPromise → p
    │
    └─ fn ? p.then(fn.bind(this) || fn) : p

[スケジューラとの関連]
queueJob(job) → queueFlush()
    │
    └─ currentFlushPromise = resolvedPromise.then(flushJobs)
           │
           └─ flushJobs()
                  ├─ queue内のジョブ実行
                  ├─ flushPostFlushCbs()
                  └─ finally: currentFlushPromise = null
```

### データフロー図

```
[入力]                    [処理]                          [出力]

fn? (Function)   ───▶ nextTick()                    ───▶ Promise<void | R>
                         │
                         ├─ currentFlushPromise存在?
                         │      ├─ Yes → フラッシュ完了待ち
                         │      └─ No → 次のマイクロタスク
                         │
                         └─ fn.then()でコールバック登録

[スケジューラ側]
リアクティブ変更  ───▶ queueJob ───▶ queueFlush ───▶ flushJobs
                                        │                │
                                        ▼                ▼
                              currentFlushPromise設定  currentFlushPromise=null
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| scheduler.ts | `packages/runtime-core/src/scheduler.ts` | ソース | nextTick定義、queueJob、queueFlush、flushJobs |
| index.ts | `packages/runtime-core/src/index.ts` | ソース | nextTickのre-export |
