Как браузер запрашивает разрешение на расширение квоты

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


Хранилище браузера и лимиты

Браузеры накладывают ограничения на размер данных, которые можно хранить локально через IndexedDB. Эти ограничения зависят от:

  • Общего объёма доступного диска.
  • Соотношения используемого и свободного пространства.
  • Политики конкретного браузера (например, Chrome, Firefox, Safari могут использовать разные стратегии расчёта лимитов).

Если попытка записи превышает доступную квоту, браузер выбрасывает исключение QuotaExceededError. В таких случаях необходим механизм запроса разрешения на увеличение квоты.


Механизм запроса расширения квоты

Современные браузеры автоматически обрабатывают большинство запросов на хранение до определённого лимита. Для больших объёмов данных или операций с мультимедиа (например, изображения, видео, кеш больших объектов) может потребоваться явный запрос расширения квоты.

Основные шаги:

  1. Проверка доступного объёма Через API navigator.storage.estimate() можно получить текущую оценку квоты и используемого объёма:

    import { get, set, del } from 'idb-keyval';
    
    async function checkQuota() {
        if (navigator.storage && navigator.storage.estimate) {
            const { quota, usage } = await navigator.storage.estimate();
            console.log(`Используемо: ${usage} байт, Квота: ${quota} байт`);
        }
    }
    • quota — общий объём, доступный приложению.
    • usage — уже использованное пространство.
  2. Реакция на превышение квоты Если запись в IndexedDB вызывает QuotaExceededError, необходимо обработать исключение:

    try {
        await set('largeData', bigBlob);
    } catch (err) {
        if (err.name === 'QuotaExceededError') {
            console.warn('Квота хранилища превышена');
        } else {
            throw err;
        }
    }

    Здесь важно различать ошибки, связанные с квотой, и другие возможные исключения IndexedDB.

  3. Запрос разрешения на расширение квоты Стандартный IndexedDB API не позволяет явно «запрашивать больше квоты». Квота увеличивается автоматически, если:

    • Пользователь активно взаимодействует с сайтом (увеличение разрешается по событию пользователя).
    • Общий размер данных остаётся в пределах допустимого лимита браузера для сайта.

    В Chrome и некоторых Chromium-браузерах квота расширяется динамически до определённого процента свободного диска, но при записи больших Blob или ArrayBuffer рекомендуется разбивать данные на части и сохранять постепенно, чтобы браузер мог оценивать использование и расширять квоту по мере необходимости.


Практические рекомендации при работе с Idb-keyval и большими данными

  • Использовать поточное хранение: Для больших файлов лучше разбивать на чанки и сохранять их по ключам file_1, file_2 и т.д. Это предотвращает резкие превышения лимита.

  • Регулярно проверять квоту: Вызов navigator.storage.estimate() перед и после крупных операций позволяет прогнозировать возможные ошибки.

  • Обработка исключений: Всегда использовать try/catch при set или del для безопасной обработки QuotaExceededError.

  • Оптимизация хранения: Минимизировать объём данных в IndexedDB, удалять устаревшие записи и избегать избыточного дублирования данных.


Пример интеграции проверки квоты с Idb-keyval

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

async function storeData(key, data) {
    try {
        const { quota, usage } = await navigator.storage.estimate();
        console.log(`Используемо: ${usage} байт, Квота: ${quota} байт`);

        // Если данных слишком много для текущей квоты
        if (usage + data.size > quota * 0.9) {
            console.warn('Данные слишком большие, возможно превышение квоты');
        }

        await set(key, data);
        console.log('Данные успешно сохранены');
    } catch (err) {
        if (err.name === 'QuotaExceededError') {
            console.error('Не удалось сохранить данные: превышена квота');
        } else {
            throw err;
        }
    }
}

В этом примере данные сохраняются только после проверки текущего использования квоты. Такой подход снижает вероятность сбоев и позволяет управлять локальным хранилищем более предсказуемо.