IndexedDB
Объектная NoSQL-БД в браузере: гигабайты структурированных данных, транзакции, индексы.
Что это
Транзакционная key-value/object-store БД, асинхронная, на основе callback'ов и событий (не Promise — старое API). Хранит JS-объекты, Blob'ы, файлы. Каждый origin изолирован. Размер — в gigabyte-range. Pain в работе → обёрток типа idb, Dexie, localForage почти всегда лучше.
Базовое использование (без обёртки)
// 1. Открыть БД (создаст если нет, версия — для миграций)
const request = indexedDB.open('podcasts', 1);
request.onupgradeneeded = (e) => {
const db = e.target.result;
// создаём store с keyPath
const store = db.createObjectStore('episodes', { keyPath: 'guid' });
store.createIndex('byPubDate', 'pubDate', { unique: false });
};
request.onsuccess = (e) => {
const db = e.target.result;
// 2. Транзакция
const tx = db.transaction('episodes', 'readwrite');
const store = tx.objectStore('episodes');
store.put({ guid: 'ep-1', title: 'First', pubDate: Date.now() });
store.get('ep-1').onsuccess = (e) => console.log(e.target.result);
tx.oncomplete = () => console.log('tx done');
};
request.onerror = (e) => console.error(e.target.error);
С обёрткой idb (Promise-based)
import { openDB } from 'idb';
const db = await openDB('podcasts', 1, {
upgrade(db) {
db.createObjectStore('episodes', { keyPath: 'guid' });
},
});
await db.put('episodes', { guid: 'ep-1', title: 'First' });
const ep = await db.get('episodes', 'ep-1');
const all = await db.getAll('episodes');
await db.delete('episodes', 'ep-1');
Структура
- Database → версия → миграция через
onupgradeneeded - Object Store → как таблица (но без схемы), у объекта
keyPath - Index → дополнительный путь для поиска (не только по keyPath)
- Transaction → атомарный, readonly/readwrite/versionchange
- Cursor → итерация по записям
Поддержка
Все современные браузеры. Доступно из Window, Worker и Service Worker.
Подводные камни
- API на callback'ах — без обёртки больно
- Транзакция автокоммитится при возврате в event loop → нельзя
awaitвнутри транзакции после .netawait(только sync шаги илиtx.done) - Версии — целые числа, миграция через
onupgradeneededтолько при увеличении версии - Safari исторически глючил с большими записями
- Не сериализуется через
JSON.stringify(Blob → потеря); используй родной структурированный клон
vs альтернативы
| Когда | |
|---|---|
| IndexedDB | Много структурированных записей, нужны индексы |
| OPFS | Большие файлы (видео, БД-файлы), sync API в Worker |
| localStorage | Несколько мелких настроек (до ~5 MB) |
| Cookies | Нужно отправлять на сервер автоматически |
Используется в bootcamp
- Podcast Player — хранение метаданных эпизодов, прогресса прослушивания
- AsyncRace — БД гаража (можно простую через IDB вместо localStorage)
Ссылки
🎓 Источники
- 🎓 JavaScript в браузере: Web API (часть 1) · TimurShemsedinov · 2019-10-10
window.indexedDB— IDBFactory,openбазы, транзакции, вставка/чтение.
- 🎓 🧩 IndexedDB — сравнение три варианта доступа — нативное API, модель + репозиторий · TimurShemsedinov · 2025-07-05