Idb-keyval — это простая обертка над IndexedDB, обеспечивающая удобное хранение пар ключ–значение в браузере. Она идеально подходит для кэширования ответов API, поскольку позволяет сохранять данные локально и извлекать их асинхронно, не блокируя основной поток выполнения.
Для начала необходимо установить библиотеку:
npm install idb-keyval
После установки можно импортировать основные функции:
import { get, set, del, clear, keys } from 'idb-keyval';
set(key, value) — сохраняет значение value
по ключу key.get(key) — возвращает сохраненное значение по ключу
key.del(key) — удаляет значение по ключу
key.clear() — очищает все данные.keys() — возвращает массив всех ключей.Все методы возвращают промисы, что позволяет работать с ними
асинхронно и использовать async/await.
Кэширование API-ответов с помощью Idb-keyval состоит из нескольких ключевых этапов:
function getCacheKey(url, params) {
return `${url}?${new URLSearchParams(params).toString()}`;
}
async function fetchWithCache(url, params) {
const cacheKey = getCacheKey(url, params);
const cached = await get(cacheKey);
if (cached) return cached;
const response = await fetch(url + '?' + new URLSearchParams(params));
const data = await response.json();
await set(cacheKey, data);
return data;
}
async function fetchWithCacheAndTTL(url, params, ttl = 3600) {
const cacheKey = getCacheKey(url, params);
const cached = await get(cacheKey);
if (cached && (Date.now() - cached.timestamp < ttl * 1000)) {
return cached.data;
}
const response = await fetch(url + '?' + new URLSearchParams(params));
const data = await response.json();
await set(cacheKey, { data, timestamp: Date.now() });
return data;
}
Хранение объектов с метаданными Idb-keyval позволяет хранить сложные объекты, включая метаданные:
await set('user_123', {
data: { name: 'Иван', age: 30 },
fetchedAt: Date.now(),
source: 'API'
});
Очистка устаревшего кэша Можно периодически проверять ключи и удалять устаревшие данные:
async function cleanupCache(ttl = 3600) {
const allKeys = await keys();
for (const key of allKeys) {
const entry = await get(key);
if (entry.timestamp && (Date.now() - entry.timestamp > ttl * 1000)) {
await del(key);
}
}
}
Хранение больших массивов данных Idb-keyval оптимизирован под хранение объектов любых размеров. Для больших коллекций лучше разделять данные на части по ключам, чтобы избежать проблем с производительностью:
await set('posts_page_1', page1Data);
await set('posts_page_2', page2Data);
Использование нескольких хранилищ Idb-keyval позволяет создавать собственные хранилища для разделения данных:
import { Store, get, set } from 'idb-keyval';
const apiCacheStore = new Store('api-cache', 'responses');
await set('user_123', userData, apiCacheStore);
const cachedUser = await get('user_123', apiCacheStore);
Это позволяет изолировать разные типы данных, например кэш API и настройки пользователя, и управлять ими отдельно.
Асинхронная инвалидация кэша Можно запускать очистку старых данных в фоне, не блокируя основной поток:
setTimeout(() => cleanupCache(3600), 0);
Комбинирование с Service Worker Idb-keyval хорошо интегрируется с Service Worker для оффлайн-кэширования: ответы API сохраняются в IndexedDB и используются при отсутствии сети.
self.addEventListener('fetch', async event => {
const url = new URL(event.request.url);
if (url.pathname.startsWith('/api/')) {
const cacheKey = url.toString();
const cached = await get(cacheKey);
if (cached) {
event.respondWith(new Response(JSON.stringify(cached)));
} else {
const response = await fetch(event.request);
const data = await response.clone().json();
await set(cacheKey, data);
event.respondWith(response);
}
}
});
Idb-keyval предоставляет простой, надежный и асинхронный способ кэширования API-ответов, минимизируя количество сетевых запросов и улучшая производительность веб-приложений.