Добавление запросов в очередь

Workbox предоставляет мощный модуль workbox-background-sync, позволяющий организовать отложенную обработку запросов, когда устройство временно находится вне сети. Основной элемент — очередь запросов, которая гарантирует, что сетевые действия не будут потеряны и будут выполнены при восстановлении соединения.

Очередь создаётся через класс workbox.backgroundSync.Queue:

import { Queue } from 'workbox-background-sync';

const myQueue = new Queue('myQueueName', {
  maxRetentionTime: 24 * 60 // время хранения в минутах
});

Ключевые параметры:

  • name — уникальное имя очереди, под которым сохраняются запросы в IndexedDB.
  • maxRetentionTime — максимальное время хранения неудачных запросов, после которого они удаляются.

Добавление запросов в очередь

Для того чтобы поместить запрос в очередь, используется метод pushRequest:

const request = new Request('/api/data', {
  method: 'POST',
  body: JSON.stringify({ foo: 'bar' }),
  headers: { 'Content-Type': 'application/json' }
});

myQueue.pushRequest({ request });

Особенности:

  • Если запрос выполнен успешно, pushRequest завершает работу без сохранения.
  • Если сеть недоступна или сервер возвращает ошибку, запрос сохраняется в очереди и будет повторно отправлен позже.
  • Метод принимает объект с ключом request, а также необязательный параметр metadata, позволяющий хранить дополнительную информацию, необходимую для обработки запроса после восстановления соединения.

Пример с метаданными:

myQueue.pushRequest({
  request,
  metadata: { userId: 123, timestamp: Date.now() }
});

Метаданные будут доступны при последующей обработке запроса через replayRequests.


Автоматическое повторение запросов

После добавления в очередь запросы можно автоматически повторять при восстановлении соединения с помощью встроенного слушателя события sync:

self.addEventListener('sync', (event) => {
  if (event.tag === 'myQueueName') {
    event.waitUntil(myQueue.replayRequests());
  }
});

Принцип работы:

  1. Браузер инициирует событие sync после восстановления сети.
  2. Метод replayRequests перебирает все сохранённые запросы.
  3. Каждый запрос выполняется заново, ошибки логируются.
  4. Успешно выполненные запросы удаляются из очереди.

Настройка политики повторов

Класс Queue позволяет переопределить поведение повторной отправки через колбэк onSync:

const myQueue = new Queue('myQueueName', {
  onSync: async ({ queue }) => {
    let entry;
    while ((entry = await queue.shiftRequest())) {
      try {
        await fetch(entry.request);
      } catch (error) {
        await queue.unshiftRequest(entry); // возвращаем запрос в очередь
        throw error;
      }
    }
  }
});

Особенности:

  • Позволяет реализовать кастомные стратегии повторов, например, с экспоненциальной задержкой.
  • Можно обрабатывать метаданные для логики повторной отправки.

Интеграция с Workbox routing

Очереди запросов тесно интегрируются с маршрутизацией Workbox. Пример для POST-запросов к API:

import { registerRoute } from 'workbox-routing';
import { NetworkOnly } from 'workbox-strategies';
import { Queue } from 'workbox-background-sync';

const bgSyncQueue = new Queue('apiQueue');

registerRoute(
  ({ url, request }) => url.pathname.startsWith('/api/') && request.method === 'POST',
  new NetworkOnly({
    plugins: [{
      fetchDidFail: async ({ request }) => {
        await bgSyncQueue.pushRequest({ request });
      }
    }]
  }),
  'POST'
);

Преимущества такой схемы:

  • Любые неудачные POST-запросы автоматически попадают в очередь.
  • Код сетевой логики остаётся чистым и отделённым от механизма повторов.
  • Поддерживается offline-first подход для критичных операций.

Мониторинг и управление очередью

Методы класса Queue позволяют:

  • Получить текущее количество запросов в очереди:

    const queueLength = await myQueue.getAll().then(entries => entries.length);
  • Очистить очередь:

    await myQueue.deleteQueue();
  • Повторно отправить все запросы вручную:

    await myQueue.replayRequests();

Эти методы полезны для реализации административных инструментов и отладки.


Хранение данных

Все запросы в очереди сохраняются в IndexedDB. Workbox автоматически сериализует объект Request и метаданные, что обеспечивает:

  • Надёжное хранение даже после перезагрузки страницы.
  • Возможность повторной отправки без потери информации.
  • Прозрачное управление пространством хранения через maxRetentionTime.

Лучшие практики

  • Использовать очереди для POST, PUT, DELETE запросов, критичных для данных пользователя.
  • Не хранить в очереди чувствительные данные без шифрования.
  • Обрабатывать ошибки повторов и реализовывать ограничение числа попыток для предотвращения бесконечных циклов.
  • При интеграции с routing применять fetchDidFail для автоматического добавления запросов в очередь.

Эта схема позволяет создавать приложения, которые надёжно работают офлайн и автоматически синхронизируются с сервером при восстановлении сети, используя минимальный и понятный API Workbox.