Работа с офлайн-функциональностью в современных веб-приложениях требует надежного механизма хранения пользовательских действий до момента восстановления соединения. Workbox предоставляет инструменты для создания очередей запросов, которые гарантируют доставку данных на сервер, даже если устройство пользователя временно потеряло соединение.
Ключевой объект для этого — Background Sync. Он
позволяет помещать запросы в очередь, если сеть недоступна, и
автоматически повторно отправлять их при восстановлении соединения.
Workbox предоставляет абстракцию
workbox.backgroundSync.Queue, которая упрощает управление
такими очередями.
Для создания очереди достаточно импортировать соответствующий модуль и создать экземпляр:
import { Queue } from 'workbox-background-sync';
const userActionsQueue = new Queue('userActionsQueue', {
maxRetentionTime: 24 * 60 // время хранения элементов в очереди в минутах
});
Ключевые параметры:
name — уникальное имя очереди, по которому Workbox
хранит данные в IndexedDB.maxRetentionTime — максимальное время хранения
элементов в очереди. После его истечения элемент удаляется, даже если не
удалось отправить запрос на сервер.Когда пользователь выполняет действие, требующее сетевого запроса, необходимо проверять доступность сети и при необходимости помещать запрос в очередь:
async function sendUserAction(request) {
try {
const response = await fetch(request);
if (!response.ok) throw new Error('Network error');
return response;
} catch (error) {
await userActionsQueue.pushRequest({ request });
console.log('Действие добавлено в очередь для последующей отправки');
}
}
pushRequest принимает объект с полем
request, которое может быть экземпляром
Request или объектом, совместимым с fetch. Все добавленные
элементы сохраняются в IndexedDB и автоматически отправляются, когда
сеть станет доступной.
Workbox позволяет управлять стратегией повторной
отправки. Очередь может использовать обработчик
onSync, который вызывается при срабатывании Background
Sync:
const queue = new Queue('userActionsQueue', {
onSync: async ({ queue }) => {
let entry;
while ((entry = await queue.shiftRequest())) {
try {
await fetch(entry.request);
console.log('Действие успешно отправлено');
} catch (err) {
console.error('Не удалось отправить действие, возвращаем в очередь', err);
await queue.unshiftRequest(entry);
break;
}
}
}
});
Особенности:
shiftRequest() извлекает следующий элемент из
очереди.unshiftRequest().while позволяет обрабатывать все элементы очереди
по мере их доступности.Очередь пользовательских действий работает внутри Service Worker. Для интеграции достаточно зарегистрировать обработчик fetch, который будет направлять запросы в очередь при недоступной сети:
self.addEventListener('fetch', (event) => {
const request = event.request;
if (request.method === 'POST' && request.url.includes('/api/user-action')) {
event.respondWith(
(async () => {
try {
return await fetch(request);
} catch (error) {
await userActionsQueue.pushRequest({ request });
return new Response(JSON.stringify({ status: 'queued' }), {
headers: { 'Content-Type': 'application/json' }
});
}
})()
);
}
});
Таким образом, любое действие пользователя, требующее POST-запроса, автоматически добавляется в очередь при отсутствии сети, а клиент получает подтверждение о сохранении действия для последующей отправки.
Workbox гарантирует сохранение порядка добавления элементов. Это особенно важно для сценариев, где порядок операций критичен, например, при обновлении состояния объекта на сервере. Все элементы очереди выполняются последовательно, и только после успешного завершения одного запроса выполняется следующий.
Workbox предоставляет методы для управления очередями:
queue.getAll() — получить все элементы в очереди.queue.deleteEntry(entry) — удалить конкретный
элемент.queue.replayRequests() — повторно отправить все
элементы, даже если Background Sync не сработал автоматически.maxRetentionTime, чтобы очередь не
разрасталась бесконтрольно.onSync, чтобы избежать
застревания элементов в очереди.Эта структура очередей в Workbox позволяет реализовать надёжную офлайн-работу, гарантируя доставку всех действий пользователя на сервер даже при нестабильном соединении.