前回からのつづき
前回、検索の要となる IDBKeyRangeオブジェクトの使い方を説明しましたが、今回は、その続きとなります。
データの取得において、判断に迷う getAll()とcursorについて、その判断基準と注意点について説明します。
【実務で迷わない】IndexedDBの getAll() vs cursor 徹底比較
結論
- 少量データ → getAll() でOK(シンプル)
- 大量データ → cursor 一択(安全・高性能)
- ページング・無限スクロール → cursor 必須
👉 迷ったら「データ量」で判断するのが実務的。
getAll() の特徴
const request = store.getAll(null, 100)
✔ メリット
- シンプルで書きやすい
- 一括で配列として取得できる
- 非同期処理が少なくて済む
❌ デメリット
- 一気にメモリへ読み込む
- データが多いとフリーズの原因
- 途中から取得(ページング)ができない
向いているケース
- 設定データ(数十件)
- マスタデータ(数百件まで)
- 初期表示で全部必要な場合
cursor の特徴
const request = store.openCursor()
request.onsuccess = (event) => {
const cursor = event.target.result
if (cursor) {
console.log(cursor.value)
cursor.continue()
}
}
✔ メリット
- 1件ずつ処理できる(メモリに優しい)
- 大量データでも安全
- 途中停止・再開ができる
- ページング実装が可能
❌ デメリット
- コードが少し複雑
- 非同期処理が増える
- 配列としてまとめる場合は自前処理が必要
向いているケース
- ログデータ
- 大量レコード(数千〜)
- 無限スクロール
- バックグラウンド処理
実務での使い分け
| 観点 | getAll() | cursor |
|---|---|---|
| 実装の簡単さ | ◎ | △ |
| パフォーマンス | △(大量で危険) | ◎ |
| メモリ効率 | ❌ | ◎ |
| ページング | ❌ | ◎ |
| 小規模データ | ◎ | △ |
| 大規模データ | ❌ | ◎ |
👉 getAll()の使用は簡易的、基本的には、cursor を使用する。
よくある事故パターン
store.getAll()
👉 データが増えた瞬間に…
- メモリ使用量急増
- UIフリーズ
- 最悪クラッシュ
👉 最初は問題なくても、運用後に壊れるのが怖い。
実務でのおすすめパターン
- 安全な上限付き取得
store.getAll(null, 100)
👉 小〜中規模ならこれでOK。
- 本番向け(安全設計)
const results = []
store.openCursor().onsuccess = (e) => {
const cursor = e.target.result
if (!cursor) return
results.push(cursor.value)
if (results.length < 100) {
cursor.continue()
}
}
👉 自前で「最大件数」を制御。
さらに実務っぽい話
なぜ cursor が重要なのか?
👉 IndexedDBは「ローカルDB」。
つまり:
- ユーザー環境によってデータ量が読めない
- 数万件になることも普通にある
👉 安全側に倒す設計が必要
まとめ
- getAll() は便利だが、大量データに弱い
- cursor は面倒だが、安全で拡張性が高い
実務では「最初から cursor 前提」で設計する方が事故が少ない。
一言アドバイス(差別化ポイント)
👉 「最初は getAll → 後で cursor に書き換え」では遅い。
最初から:
- データ増加を前提に設計する
- cursorベースで組む
👉 これだけで「壊れないアプリ」になります。