Использование async/await с idb-keyval

idb-keyval — это небольшая, удобная библиотека для работы с IndexedDB в браузерах. Она предоставляет простой интерфейс для сохранения, получения и удаления данных в хранилище IndexedDB без необходимости прямого взаимодействия с низкоуровневым API. Важным преимуществом является поддержка асинхронного синтаксиса через Promises, что позволяет эффективно использовать async/await для удобного и читаемого кода.

Базовые функции библиотеки (get, set, del, clear) возвращают промисы. Это значит, что их можно использовать внутри асинхронных функций с await для упрощения работы с асинхронными операциями.

Пример базового использования с async/await:

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

async function saveUserData() {
    await set('username', 'Alice');
    const username = await get('username');
    console.log(username); // Alice
}

Асинхронное сохранение данных

Функция set(key, value) сохраняет значение по указанному ключу. Она возвращает промис, который выполняется после успешного сохранения данных.

import { set } from 'idb-keyval';

async function storeSettings() {
    try {
        await set('theme', 'dark');
        await set('fontSize', 16);
        console.log('Настройки успешно сохранены');
    } catch (error) {
        console.error('Ошибка при сохранении настроек:', error);
    }
}

Особенности использования await set(...):

  • Можно последовательно сохранять несколько значений без вложенных .then().
  • Ошибки легко перехватывать через try/catch.
  • Вызовы могут быть выполнены параллельно через Promise.all для оптимизации производительности.
import { set } from 'idb-keyval';

async function storeMultiple() {
    try {
        await Promise.all([
            set('userId', 12345),
            set('sessionToken', 'abcde12345'),
            set('notificationsEnabled', true)
        ]);
        console.log('Все данные сохранены одновременно');
    } catch (error) {
        console.error('Ошибка при сохранении данных:', error);
    }
}

Асинхронное получение данных

Функция get(key) возвращает промис, который разрешается в значение по указанному ключу. Использование async/await делает код линейным и легко читаемым.

import { get } from 'idb-keyval';

async function loadUserData() {
    try {
        const username = await get('username');
        const theme = await get('theme');
        console.log({ username, theme });
    } catch (error) {
        console.error('Ошибка при загрузке данных:', error);
    }
}

Ключевые моменты:

  • Если ключа нет в хранилище, промис возвращает undefined.
  • Использование await позволяет обрабатывать данные сразу после получения, без цепочек .then().

Удаление и очистка данных

idb-keyval предоставляет функции del(key) и clear(). Они тоже асинхронные и отлично интегрируются с async/await.

import { del, clear } from 'idb-keyval';

async function manageStorage() {
    await del('username'); // удаление конкретного ключа
    await clear();         // полная очистка хранилища
}

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

Работа с пользовательскими хранилищами

idb-keyval позволяет создавать свои экземпляры хранилищ через createStore(dbName, storeName). Асинхронный синтаксис при этом остается тем же.

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

const userStore = createStore('userDB', 'settings');

async function saveCustomData() {
    await set('language', 'ru', userStore);
    const language = await get('language', userStore);
    console.log(language); // ru
}

Преимущества пользовательских хранилищ:

  • Изоляция данных разных модулей приложения.
  • Возможность управлять отдельными базами данных без конфликтов.
  • Легкая интеграция с async/await без изменения логики работы функций.

Обработка ошибок

Все асинхронные операции в idb-keyval могут завершиться ошибкой, поэтому рекомендуется использовать try/catch блоки или .catch() для промисов.

import { get } from 'idb-keyval';

async function safeLoad() {
    try {
        const token = await get('sessionToken');
        if (!token) throw new Error('Токен отсутствует');
        console.log('Токен загружен:', token);
    } catch (error) {
        console.error('Ошибка при работе с IndexedDB:', error);
    }
}

Комбинирование с другими асинхронными операциями

async/await с idb-keyval удобно комбинировать с любыми другими асинхронными действиями, такими как запросы к API:

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

async function syncUserProfile() {
    try {
        const profile = await fetch('/api/profile').then(res => res.json());
        await set('profile', profile);
        const cachedProfile = await get('profile');
        console.log(cachedProfile);
    } catch (error) {
        console.error('Ошибка синхронизации профиля:', error);
    }
}

Такой подход обеспечивает чистый, линейный код, который легко читать и отлаживать, в отличие от цепочек промисов .then()/.catch().


idb-keyval в сочетании с async/await превращает работу с IndexedDB из сложного процесса с множеством колбэков в удобный и современный асинхронный поток, позволяя сохранять, загружать и управлять данными с минимальным количеством кода и максимальной читаемостью.