Почему нельзя использовать idb-keyval синхронно

Библиотека Idb-keyval построена на основе IndexedDB — низкоуровневого браузерного API для хранения структурированных данных на стороне клиента. IndexedDB по своей природе асинхронна, что связано с архитектурой браузеров и необходимостью предотвращать блокировку основного потока выполнения JavaScript. Любая операция чтения или записи данных выполняется через события и промисы, а не напрямую возвращает результат.

Idb-keyval полностью наследует эту асинхронность и предоставляет простой интерфейс для работы с ключами и значениями, используя промисы (Promise). Например:

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

set('username', 'alice').then(() => {
    console.log('Имя пользователя сохранено');
});

get('username').then(value => {
    console.log('Значение:', value);
});

Даже простое чтение данных не может быть синхронным, потому что IndexedDB работает с отдельным потоком и использует события для уведомления о завершении операции. Любая попытка сделать get('username') синхронно вернёт промис, а не само значение.


Почему синхронный доступ невозможен

  1. Изоляция от основного потока IndexedDB проектировалась для хранения больших объёмов данных без блокировки пользовательского интерфейса. Если бы доступ был синхронным, каждая операция записи или чтения могла бы замедлить рендеринг страницы или сделать интерфейс «замороженным».

  2. Асинхронные транзакции Все операции IndexedDB происходят в рамках транзакций. Транзакции открываются, выполняются и закрываются с помощью событий onsuccess и onerror. Промисы в Idb-keyval служат обёрткой над этими событиями, позволяя работать с результатами после завершения транзакции.

  3. Отсутствие блокирующих API Браузеры не предоставляют синхронного API для IndexedDB. Даже попытка использовать await без асинхронной функции приведёт к ошибке, а любые обходные методы (например, синхронные запросы через localStorage) не поддерживают объёмные или структурированные данные и не могут гарантировать ту же целостность.


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

  • Невозможность немедленного получения данных Любое ожидание результата через переменную без использования then или await приведёт к тому, что переменная будет содержать промис, а не значение.

  • Потенциальные ошибки при последовательных операциях Если попытаться построить цепочку операций синхронно, одна запись может не завершиться до чтения следующей, что вызовет логические ошибки и неконсистентные данные.

  • Блокировка интерфейса невозможна Поскольку синхронного метода нет, любые подходы через цикл ожидания (while(!done) {}) будут либо бессмысленны, либо заморозят страницу. Это архитектурная особенность, а не баг библиотеки.


Правильный подход к использованию Idb-keyval

  • Использование async/await
import { set, get } from 'idb-keyval';

async function saveAndLoad() {
    await set('theme', 'dark');
    const theme = await get('theme');
    console.log('Текущая тема:', theme);
}
  • Использование промисов напрямую
set('token', 'abc123')
    .then(() => get('token'))
    .then(value => console.log('Token:', value))
    .catch(err => console.error(err));
  • Составление цепочек операций через промисы Позволяет управлять последовательностью операций без блокировки интерфейса и обеспечивает корректное завершение всех транзакций.

Вывод ключевых моментов

  • Idb-keyval асинхронен по своей сути, синхронное использование невозможно.
  • Все операции чтения и записи возвращают промисы.
  • Любая попытка заставить библиотеку работать синхронно приведёт к неправильной обработке данных или блокировке интерфейса.
  • Для корректной работы следует использовать async/await или цепочки промисов, уважая архитектуру IndexedDB.

Idb-keyval обеспечивает удобный и безопасный доступ к IndexedDB, но синхронные методы для мгновенного получения значений в текущем потоке JavaScript не поддерживаются и противоречат проектной модели браузеров.