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());
}
});
Принцип работы:
sync после восстановления
сети.replayRequests перебирает все сохранённые
запросы.Класс 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. Пример для 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'
);
Преимущества такой схемы:
Методы класса Queue позволяют:
Получить текущее количество запросов в очереди:
const queueLength = await myQueue.getAll().then(entries => entries.length);Очистить очередь:
await myQueue.deleteQueue();Повторно отправить все запросы вручную:
await myQueue.replayRequests();Эти методы полезны для реализации административных инструментов и отладки.
Все запросы в очереди сохраняются в IndexedDB.
Workbox автоматически сериализует объект Request и
метаданные, что обеспечивает:
maxRetentionTime.fetchDidFail для
автоматического добавления запросов в очередь.Эта схема позволяет создавать приложения, которые надёжно работают офлайн и автоматически синхронизируются с сервером при восстановлении сети, используя минимальный и понятный API Workbox.