Idb-keyval представляет собой минималистичную библиотеку для работы с IndexedDB в браузере. Основная цель — упростить асинхронное хранение ключ-значение без необходимости писать громоздкие промисы и обработчики ошибок для самой IndexedDB. Однако в некоторых случаях IndexedDB может быть недоступна: например, в приватных режимах браузера или при ограничениях платформы. В таких ситуациях полезно реализовать fallback на localStorage, чтобы данные не терялись.
Библиотека предоставляет следующие ключевые функции:
set(key, value): сохраняет значение value
по ключу key.get(key): получает значение по ключу
key.del(key): удаляет значение по ключу
key.clear(): очищает все хранилище.keys(): возвращает массив всех ключей.Пример базового использования:
import { set, get } from 'idb-keyval';
await set('user', { name: 'Alice', age: 25 });
const user = await get('user');
console.log(user); // { name: 'Alice', age: 25 }
Все операции возвращают промисы, что позволяет использовать
async/await или цепочки .then().
Некоторые браузеры в приватных режимах или при строгих настройках
блокируют IndexedDB. В этом случае вызовы set или
get могут вызывать ошибки или просто не сохранять данные.
Чтобы избежать потери данных, реализуется fallback на localStorage:
Для корректного fallback необходимо обернуть все операции Idb-keyval в функции, проверяющие доступность IndexedDB:
import { set as idbSet, get as idbGet } from 'idb-keyval';
function isIndexedDBAvailable() {
try {
return !!window.indexedDB;
} catch {
return false;
}
}
async function setItem(key, value) {
if (isIndexedDBAvailable()) {
try {
await idbSet(key, value);
return;
} catch (e) {
console.warn('IndexedDB недоступна, сохраняем в localStorage', e);
}
}
localStorage.setItem(key, JSON.stringify(value));
}
async function getItem(key) {
if (isIndexedDBAvailable()) {
try {
const value = await idbGet(key);
if (value !== undefined) return value;
} catch (e) {
console.warn('Ошибка при чтении из IndexedDB', e);
}
}
const stored = localStorage.getItem(key);
return stored ? JSON.parse(stored) : undefined;
}
Ключевые моменты:
try/catch.JSON.stringify/JSON.parse
для совместимости с localStorage.Когда fallback срабатывает, возникает проблема синхронизации: данные, сохранённые в localStorage, могут устареть, если позже IndexedDB становится доступна. Стратегии синхронизации:
async function migrateToIDB() {
if (!isIndexedDBAvailable()) return;
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
const value = JSON.parse(localStorage.getItem(key));
await idbSet(key, value);
}
localStorage.clear();
}
Для полноценного использования fallback можно обернуть все методы:
async function delItem(key) {
if (isIndexedDBAvailable()) {
try {
await idbDel(key);
} catch {
localStorage.removeItem(key);
}
} else {
localStorage.removeItem(key);
}
}
async function clearAll() {
if (isIndexedDBAvailable()) {
try {
await idbClear();
} catch {
localStorage.clear();
}
} else {
localStorage.clear();
}
}
async function getAllKeys() {
if (isIndexedDBAvailable()) {
try {
return await idbKeys();
} catch {
return Object.keys(localStorage);
}
} else {
return Object.keys(localStorage);
}
}
try/catch для
предотвращения неожиданных ошибок.Эта стратегия позволяет сочетать преимущества IndexedDB — асинхронность и большой объём хранилища — с надёжностью localStorage как резервного варианта. Такой подход обеспечивает стабильность приложения в любых условиях работы браузера.