Библиотека idb-keyval предоставляет удобный интерфейс
для работы с IndexedDB в виде простых функций get,
set, del, update и других. Особое
внимание заслуживает функция update, которая позволяет
изменять значение по ключу, основываясь на текущем состоянии. Понимание
обработки ошибок и возможности отката транзакции в update
критично для надёжного управления состоянием.
updateФункция update принимает два аргумента:
update(key, updater)
Пример базового использования:
import { update } from 'idb-keyval';
await update('counter', value => (value || 0) + 1);
В этом примере update получает текущее значение
counter, увеличивает его на 1 и сохраняет обратно.
updateupdate выполняется в рамках транзакции IndexedDB. Любая
ошибка, возникшая внутри функции updater, приводит к
откату транзакции. Это ключевое отличие от
использования get + set вручную, где ошибки
могут оставить базу в частично изменённом состоянии.
Пример с выбрасыванием ошибки:
await update('user', value => {
if (!value) throw new Error('Пользователь не найден');
return { ...value, active: true };
}).catch(err => {
console.error('Ошибка обновления:', err);
});
В этом случае:
.catch или try/catch.updaterФункция updater не поддерживает асинхронный код
напрямую. Любое использование await внутри неё
приведёт к ошибке или некорректному результату. IndexedDB транзакции
синхронны на уровне обработки изменений данных, поэтому весь код внутри
updater должен быть синхронным.
Неправильный пример:
await update('settings', async value => {
const response = await fetch('/config'); // ❌ не сработает
return { ...value, config: await response.json() };
});
Правильный подход — сначала получить необходимые данные, затем
выполнить update синхронно:
const response = await fetch('/config');
const config = await response.json();
await update('settings', value => ({ ...value, config }));
Если внутри update выбрасывается ошибка:
Это гарантирует атомарность операции, что особенно важно при работе с комплексными структурами данных.
await update('cart', cart => {
if (!cart.items.length) throw new Error('Корзина пуста');
if (cart.total > 1000) throw new Error('Превышен лимит суммы');
return { ...cart, checkedOut: true };
}).catch(err => console.log(err.message));
В этом примере любое нарушение условий прерывает обновление, и состояние корзины остаётся прежним.
await update('profile', profile => {
if (!profile.email.includes('@')) throw new Error('Некорректный email');
return { ...profile, verified: true };
});
Ошибки валидации автоматически откатывают изменения, что предотвращает сохранение некорректных данных.
.catch или try/catch для логирования и
пользовательских уведомлений.Функция update в idb-keyval сочетает в себе
простоту записи и атомарность транзакций. Понимание поведения при
ошибках и правильная организация кода внутри updater позволяют безопасно
управлять данными и предотвращать неконсистентность в IndexedDB.