Отличие update от последовательности get/set

Библиотека idb-keyval предоставляет минималистичный интерфейс для работы с IndexedDB в браузере. Она упрощает операции хранения и извлечения данных, скрывая сложность асинхронного API IndexedDB. Основные методы включают get, set, del, update, а также утилиты для работы с транзакциями и коллекциями данных.

Метод get и метод set

Метод get(key) используется для извлечения значения по ключу. Он возвращает промис, который резолвится значением из хранилища или undefined, если ключ отсутствует:

import { get, set } from 'idb-keyval';

await set('username', 'Alice');
const username = await get('username'); // 'Alice'

Метод set(key, value) записывает или обновляет значение по ключу. Если ключ уже существует, старое значение перезаписывается новым.

await set('username', 'Bob');
const upd atedUsername = await get('username'); // 'Bob'

Таким образом, комбинация get и set позволяет реализовать обновление значения вручную: сначала получить текущее значение, изменить его и записать обратно.

Метод update

Метод upd ate(key, updater) объединяет операции чтения и записи в одну атомарную операцию. Аргумент updater — это функция, которая принимает текущее значение ключа и возвращает новое.

import { upd ate } from 'idb-keyval';

await upd ate('counter', val => (val || 0) + 1);
const counter = await get('counter'); // 1, если ключа не было ранее

Ключевые особенности update:

  • Атомарность: чтение и запись происходят в рамках одной транзакции, что предотвращает состояние гонки.
  • Упрощение кода: не требуется отдельно вызывать get и set.
  • Безопасность для конкурентного доступа: несколько вызовов update на одном ключе корректно увеличивают значение, не затирая изменения других процессов.

Сравнение update и последовательности get/se t

Характеристика get + set update
Количество операций Две операции (чтение и запись) Одна атомарная операция
Потенциальные состояния гонки Возможны при параллельных модификациях Исключены благодаря транзакции
Чистота кода Требуется ручная проверка и модификация Лаконичный, безопасный синтаксис
Поддержка конкурентных обновлений Нужно вручную реализовывать блокировку Автоматически управляется библиотекой

Примеры практического использования

Сценарий 1: Счетчик кликов Использование последовательности get/se t:

const clicks = await get('clicks') || 0;
await se t('clicks', clicks + 1);

Использование update:

await upd ate('clicks', val => (val || 0) + 1);

Разница становится заметна при нескольких параллельных вызовах. При get/se t есть риск потерять некоторые инкременты, если они выполняются почти одновременно. update решает эту проблему за счет атомарной транзакции.

Сценарий 2: Обновление настроек пользователя Предположим, нужно добавить новое поле в объект настроек:

await upd ate('settings', settings => ({
    ...settings,
    theme: 'dark'
}));

Аналогично через get/se t потребовалось бы:

const settings = await get('settings') || {};
settings.theme = 'dark';
await se t('settings', settings);

update обеспечивает более читаемый и надежный код, особенно при работе с сложными структурами данных.

Заключение по применению

Метод update предпочтителен, когда требуется модифицировать существующее значение в хранилище с сохранением атомарности и безопасности. Последовательность get/set подходит для простых операций записи или когда необходимо выполнить дополнительные проверки между чтением и записью, но требует осторожности при параллельных обновлениях.

Использование update повышает надежность кода и снижает вероятность ошибок при одновременном доступе к данным, делая работу с IndexedDB через idb-keyval более безопасной и удобной.