Idb-keyval — это простая и легковесная обёртка над IndexedDB, позволяющая работать с ключ-значение хранилищем в браузере через удобный асинхронный API. Все операции с данными возвращают промисы, что делает библиотеку удобной для интеграции с современными асинхронными потоками данных.
Основные функции библиотеки:
Пример использования базовых операций:
import { set, get, del, clear, keys } from 'idb-keyval';
// Сохранение значения
await set('username', 'Alice');
// Получение значения
const username = await get('username');
// Удаление значения
await del('username');
// Очистка хранилища
await clear();
// Получение всех ключей
const allKeys = await keys();
Все функции возвращают промисы, что делает возможным использование их
с async/await или .then().
Все операции Idb-keyval выполняются асинхронно, поэтому тестирование требует правильного управления временем ожидания результатов. Простые синхронные проверки не подходят — необходимо работать с промисами.
Пример проверки сохранения данных:
import { set, get } from 'idb-keyval';
async function testSetAndGet() {
await set('key1', 'value1');
const result = await get('key1');
if (result !== 'value1') {
throw new Error('Значение не совпадает');
}
}
Ключевой момент: тест должен ожидать завершения операции, иначе результат может быть неопределённым.
При работе с Jest функции с промисами должны возвращать промис или
использовать async/await. Пример:
import { set, get, del } from 'idb-keyval';
test('сохранение и получение значения', async () => {
await set('testKey', 'testValue');
const value = await get('testKey');
expect(value).toBe('testValue');
});
test('удаление значения', async () => {
await set('testKey', 'testValue');
await del('testKey');
const value = await get('testKey');
expect(value).toBeUndefined();
});
Если не использовать async/await или не возвращать
промис, Jest завершит тест до окончания операции IndexedDB, и тест может
давать ложноположительные или ложноотрицательные результаты.
Idb-keyval автоматически обрабатывает большинство ошибок IndexedDB, но при тестировании важно учитывать возможные сбои:
import { set, get } from 'idb-keyval';
test('ошибка при чтении несуществующего ключа', async () => {
try {
const value = await get('nonExistentKey');
expect(value).toBeUndefined();
} catch (err) {
throw new Error('Произошла непредвиденная ошибка: ' + err.message);
}
});
Асинхронное тестирование должно предусматривать обработку исключений
через try/catch, чтобы тест корректно фиксировал ошибки, не
прерывая выполнение.
Idb-keyval поддерживает параллельные операции, однако при тестировании важно убедиться, что промисы разрешены в правильном порядке, если это важно для логики приложения.
Пример параллельного сохранения:
import { set, get } from 'idb-keyval';
async function testParallelSets() {
const promises = [
set('key1', 'value1'),
set('key2', 'value2'),
set('key3', 'value3')
];
await Promise.all(promises);
const values = await Promise.all([
get('key1'),
get('key2'),
get('key3')
]);
if (values[0] !== 'value1' || values[1] !== 'value2' || values[2] !== 'value3') {
throw new Error('Ошибка при параллельной записи');
}
}
Promise.all гарантирует, что все операции завершены
перед проверкой результата.
Для корректного тестирования важно очищать хранилище между тестами, чтобы состояние одного теста не влияло на другой:
import { clear } from 'idb-keyval';
beforeEach(async () => {
await clear();
});
Использование beforeEach или afterEach
обеспечивает полную изоляцию асинхронных операций и предотвращает
непредсказуемое поведение тестов.
Idb-keyval удобно использовать с асинхронными генераторами, потоками RxJS или другими асинхронными библиотеками. Пример с асинхронным генератором:
import { set, get } from 'idb-keyval';
async function* generateKeys() {
for (let i = 1; i <= 3; i++) {
await set(`key${i}`, `value${i}`);
yield await get(`key${i}`);
}
}
(async () => {
for await (const value of generateKeys()) {
console.log(value);
}
})();
Такой подход позволяет тестировать цепочки асинхронных операций и наблюдать последовательное выполнение промисов.
async/await для всех операций
Idb-keyval.try/catch для корректной
фиксации исключений.Promise.all для параллельных операций с
последующей проверкой результатов.Idb-keyval упрощает работу с IndexedDB и делает асинхронные операции более предсказуемыми, но строгая организация тестов необходима для корректной проверки работы приложений в реальных условиях.