Idb-keyval — это лёгкая библиотека для работы с
IndexedDB в браузере, которая предоставляет простой API для сохранения,
получения и удаления данных. Одним из ключевых аспектов при
использовании IndexedDB является ограничение на объём хранимых данных,
что может привести к ошибке QuotaExceededError. Эта ошибка
возникает, когда попытка записи данных превышает доступное хранилище
браузера.
Превышение лимита хранилища Каждый браузер накладывает ограничения на объём данных, которые можно хранить в IndexedDB. Обычно лимит составляет несколько сотен мегабайт на домен, но точное значение зависит от конкретного браузера и устройства.
Множественные записи больших объектов Даже если
отдельный объект небольшой, последовательные записи большого количества
данных могут суммарно превысить лимит, что приводит к
QuotaExceededError.
Одновременные операции Многопоточные операции записи без контроля могут быстро заполнить доступное пространство.
Idb-keyval использует промисы для всех операций записи
(set, update, del). Ошибку
QuotaExceededError можно отлавливать через конструкцию
try/catch с асинхронной обработкой промисов:
import { set } from 'idb-keyval';
async function saveData(key, value) {
try {
await set(key, value);
console.log('Данные успешно сохранены');
} catch (err) {
if (err.name === 'QuotaExceededError') {
console.error('Ошибка: превышен лимит хранилища');
} else {
console.error('Произошла другая ошибка:', err);
}
}
}
Ключевой момент: проверка должна выполняться по свойству
name ошибки, а не по тексту сообщения, так как разные
браузеры формируют сообщение по-своему.
1. Очистка ненужных данных Перед повторной попыткой записи можно удалить старые или неиспользуемые ключи:
import { del } from 'idb-keyval';
await del('старый_ключ');
2. Сжатие данных Использование сжатия JSON-объектов
(например, с помощью библиотек lz-string) помогает снизить
занимаемый объём:
import LZString from 'lz-string';
const compressed = LZString.compress(JSON.stringify(largeObject));
await set('key', compressed);
3. Разделение данных на части Если объект слишком большой, его можно разбить на несколько частей и сохранять по отдельным ключам:
const chunkSize = 1024 * 100; // 100 KB
const chunks = [];
for (let i = 0; i < data.length; i += chunkSize) {
chunks.push(data.slice(i, i + chunkSize));
}
for (let j = 0; j < chunks.length; j++) {
await set(`data_part_${j}`, chunks[j]);
}
4. Отслеживание доступного объёма Для современных
браузеров возможно использование API
navigator.storage.estimate() для оценки оставшегося
пространства:
const { usage, quota } = await navigator.storage.estimate();
console.log(`Использовано: ${usage} / Доступно: ${quota}`);
Этот метод позволяет принимать решение о необходимости сжатия или удалении данных до записи.
При работе с большим количеством данных важно предусматривать стратегию отказоустойчивости:
QuotaExceededError для последующего анализа использования
хранилища.import { set, del } from 'idb-keyval';
import LZString from 'lz-string';
async function safeSet(key, value) {
try {
const compressed = LZString.compress(JSON.stringify(value));
await set(key, compressed);
} catch (err) {
if (err.name === 'QuotaExceededError') {
console.warn('Превышен лимит хранилища, очищаем старые данные...');
await del('old_key'); // удаление устаревших данных
await set(key, compressed); // повторная попытка
} else {
throw err;
}
}
}
Такой подход минимизирует вероятность потери данных и позволяет управлять лимитами браузерного хранилища в приложениях, использующих Idb-keyval.