Когда вы отправляете данные на веб-сервер, иногда запросы не выполняются. Это может быть связано с тем, что пользователь потерял соединение или сервер не работает; в любом случае вам часто захочется попробовать отправить запросы позже.
Новый API BackgroundSync — идеальное решение этой проблемы. Когда работник службы обнаруживает, что сетевой запрос не выполнен, он может зарегистрироваться для получения события sync
, которое доставляется, когда браузер считает, что подключение восстановлено. Обратите внимание, что событие синхронизации может быть доставлено , даже если пользователь покинул приложение , что делает его гораздо более эффективным, чем традиционный метод повтора неудачных запросов.
Фоновая синхронизация Workbox предназначена для упрощения использования API BackgroundSync и интеграции его использования с другими модулями Workbox. Он также реализует запасной вариант для браузеров, которые еще не поддерживают BackgroundSync.
Браузеры, поддерживающие API BackgroundSync, будут автоматически воспроизводить неудачные запросы от вашего имени с интервалом, управляемым браузером , вероятно, используя экспоненциальную задержку между попытками воспроизведения. В браузерах, которые не поддерживают API BackgroundSync, Workbox Background Sync будет автоматически пытаться воспроизвести каждый раз при запуске вашего сервис-воркера.
Основное использование
Самый простой способ использовать фоновую синхронизацию — использовать Plugin
, который автоматически ставит в очередь неудачные запросы и повторяет их при возникновении будущих событий sync
.
import {BackgroundSyncPlugin} from 'workbox-background-sync';
import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';
const bgSyncPlugin = new BackgroundSyncPlugin('myQueueName', {
maxRetentionTime: 24 * 60, // Retry for max of 24 Hours (specified in minutes)
});
registerRoute(
/\/api\/.*\/*.json/,
new NetworkOnly({
plugins: [bgSyncPlugin],
}),
'POST'
);
BackgroundSyncPlugin
подключается к обратному вызову плагина fetchDidFail
, и fetchDidFail
вызывается только в случае возникновения исключения, скорее всего, из-за сбоя сети. Это означает, что запросы не будут повторяться, если получен ответ со статусом ошибки 4xx
или 5xx
. Если вы хотите повторить все запросы, которые приводят, например, к статусу 5xx
, вы можете сделать это, добавив плагин fetchDidSucceed
в свою стратегию:
const statusPlugin = {
fetchDidSucceed: ({response}) => {
if (response.status >= 500) {
// Throwing anything here will trigger fetchDidFail.
throw new Error('Server error.');
}
// If it's not 5xx, use the response as-is.
return response;
},
};
// Add statusPlugin to the plugins array in your strategy.
Расширенное использование
Фоновая синхронизация Workbox также предоставляет класс Queue
, экземпляр которого можно создавать и добавлять в него неудачные запросы. Неудачные запросы сохраняются в IndexedDB и повторяются, когда браузер считает, что соединение восстановлено (т. е. когда он получает событие синхронизации).
Создание очереди
Чтобы создать очередь фоновой синхронизации Workbox, вам необходимо создать ее с именем очереди (которое должно быть уникальным для вашего источника ):
import {Queue} from 'workbox-background-sync';
const queue = new Queue('myQueueName');
Имя очереди используется как часть имени тега, который register()
с помощью глобального SyncManager
. Оно также используется в качестве имени хранилища объектов для базы данных IndexedDB.
Добавление запроса в очередь
Создав экземпляр очереди, вы можете добавлять в него неудачные запросы. Вы добавляете неудавшийся запрос, вызывая метод .pushRequest()
. Например, следующий код перехватывает все неудачные запросы и добавляет их в очередь:
import {Queue} from 'workbox-background-sync';
const queue = new Queue('myQueueName');
self.addEventListener('fetch', event => {
// Add in your own criteria here to return early if this
// isn't a request that should use background sync.
if (event.request.method !== 'POST') {
return;
}
const bgSyncLogic = async () => {
try {
const response = await fetch(event.request.clone());
return response;
} catch (error) {
await queue.pushRequest({request: event.request});
return error;
}
};
event.respondWith(bgSyncLogic());
});
После добавления в очередь запрос автоматически повторяется, когда сервисный работник получает событие sync
(что происходит, когда браузер считает, что подключение восстановлено). Браузеры, которые не поддерживают API BackgroundSync, будут повторять попытку очереди каждый раз при запуске сервисного работника. Для этого требуется, чтобы страница, управляющая сервисным работником, была запущена, поэтому она будет не такой эффективной.
Тестирование фоновой синхронизации Workbox
К сожалению, тестирование BackgroundSync несколько неинтуитивно и сложно по ряду причин.
Лучший способ протестировать вашу реализацию — сделать следующее:
- Загрузите страницу и зарегистрируйте своего сервисного работника.
- Выключите сеть вашего компьютера или веб-сервер.
- НЕ ИСПОЛЬЗУЙТЕ CHROME DEVTOOLS ОФФЛАЙН. Флажок «Автономный режим» в DevTools влияет только на запросы со страницы. Запросы Service Worker будут продолжать обрабатываться.
- Отправляйте сетевые запросы, которые должны быть поставлены в очередь с помощью фоновой синхронизации Workbox.
- Вы можете проверить, что запросы были поставлены в очередь, просмотрев
Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests
- Вы можете проверить, что запросы были поставлены в очередь, просмотрев
- Теперь включите сеть или веб-сервер.
Вызовите событие ранней
sync
перейдя вChrome DevTools > Application > Service Workers
, введя имя тегаworkbox-background-sync:<your queue name>
где<your queue name>
должно быть именем заданной вами очереди, а затем нажав кнопку «Синхронизировать».Вы должны увидеть, что сетевые запросы выполняются для невыполненных запросов, а данные IndexedDB теперь должны быть пустыми, поскольку запросы были успешно воспроизведены.
Типы
BackgroundSyncPlugin
Класс, реализующий обратный вызов жизненного цикла fetchDidFail
. Это упрощает добавление неудачных запросов в очередь фоновой синхронизации.
Характеристики
- конструктор
пустота
Функция
constructor
выглядит так:(name: string, options?: QueueOptions) => {...}
- имя
нить
Подробные сведения о параметрах см. в документации
workbox-background-sync.Queue
. - параметры
QueueOptions необязательно
- возвращает
Queue
Класс для управления сохранением неудачных запросов в IndexedDB и их повторной попыткой позже. Все части процесса хранения и воспроизведения можно наблюдать с помощью обратных вызовов.
Характеристики
- конструктор
пустота
Создает экземпляр Queue с заданными параметрами.
Функция
constructor
выглядит так:(name: string, options?: QueueOptions) => {...}
- имя
нить
Уникальное имя этой очереди. Это имя должно быть уникальным, поскольку оно используется для регистрации событий синхронизации и хранения запросов в IndexedDB, специфичных для этого экземпляра. Если будет обнаружено повторяющееся имя, будет выдана ошибка.
- параметры
QueueOptions необязательно
- возвращает
- имя
нить
- получить все
пустота
Возвращает все записи, срок действия которых не истек (в соответствии с
maxRetentionTime
). Все записи с истекшим сроком действия удаляются из очереди.Функция
getAll
выглядит так:() => {...}
- возвращает
Обещание<QueueEntry[]>
- popRequest
пустота
Удаляет и возвращает последний запрос в очереди (вместе с его отметкой времени и метаданными). Возвращаемый объект принимает форму:
{request, timestamp, metadata}
.Функция
popRequest
выглядит так:() => {...}
- возвращает
Обещание<QueueEntry>
- pushRequest
пустота
Сохраняет переданный запрос в IndexedDB (с его отметкой времени и всеми метаданными) в конце очереди.
Функция
pushRequest
выглядит так:(entry: QueueEntry) => {...}
- вход
ОчередьЗапись
- возвращает
Обещание<void>
- регистрациясинхронизировать
пустота
Регистрирует событие синхронизации с уникальным для этого экземпляра тегом.
Функция
registerSync
выглядит так:() => {...}
- возвращает
Обещание<void>
- повторные запросы
пустота
Просматривает каждый запрос в очереди и пытается получить его повторно. Если какой-либо запрос не удается повторно получить, он возвращается в ту же позицию в очереди (которая регистрирует повторную попытку для следующего события синхронизации).
Функция
replayRequests
выглядит так:() => {...}
- возвращает
Обещание<void>
- сдвигЗапрос
пустота
Удаляет и возвращает первый запрос в очереди (вместе с его отметкой времени и метаданными). Возвращаемый объект принимает форму:
{request, timestamp, metadata}
.shiftRequest
выглядит так:() => {...}
- возвращает
Обещание<QueueEntry>
- размер
пустота
Возвращает количество записей, присутствующих в очереди. Обратите внимание, что записи с истекшим сроком действия (по
maxRetentionTime
) также включены в этот счетчик.Функция
size
выглядит так:() => {...}
- возвращает
Обещание<число>
- unshiftЗапрос
пустота
Сохраняет переданный запрос в IndexedDB (с его отметкой времени и всеми метаданными) в начале очереди.
Функция
unshiftRequest
выглядит так:(entry: QueueEntry) => {...}
- вход
ОчередьЗапись
- возвращает
Обещание<void>
QueueOptions
Характеристики
- ForceSyncFallback
логическое значение необязательно
- Максретентионтиме
номер необязательно
- onSync
OnSyncCallback необязательно
QueueStore
Класс для управления хранением запросов из очереди в IndexedDB, индексированных по имени очереди для облегчения доступа.
Большинству разработчиков не потребуется прямой доступ к этому классу; он доступен для расширенных случаев использования.
Характеристики
- конструктор
пустота
Связывает этот экземпляр с экземпляром Queue, поэтому добавленные записи можно идентифицировать по имени их очереди.
Функция
constructor
выглядит так:(queueName: string) => {...}
- имяочереди
нить
- возвращает
- удалитьEntry
пустота
Удаляет запись для данного идентификатора.
ВНИМАНИЕ: этот метод не гарантирует, что удаленная запись принадлежит этой очереди (т. е. соответствует
queueName
). Но это ограничение приемлемо, поскольку этот класс не публикуется. Дополнительная проверка сделает этот метод медленнее, чем нужно.Функция
deleteEntry
выглядит так:(id: number) => {...}
- идентификатор
число
- возвращает
Обещание<void>
- получить все
пустота
Возвращает все записи в хранилище, соответствующие
queueName
.Функция
getAll
выглядит так:() => {...}
- возвращает
Обещание<QueueStoreEntry[]>
- popEntry
пустота
Удаляет и возвращает последнюю запись в очереди, соответствующую
queueName
.Функция
popEntry
выглядит так:() => {...}
- возвращает
Обещание<QueueStoreEntry>
- pushEntry
пустота
Добавить запись последней в очереди.
Функция
pushEntry
выглядит так:(entry: UnidentifiedQueueStoreEntry) => {...}
- вход
НеопознанныйQueueStoreEntry
- возвращает
Обещание<void>
- сдвигВвод
пустота
Удаляет и возвращает первую запись в очереди, соответствующую
queueName
.shiftEntry
выглядит так:() => {...}
- возвращает
Обещание<QueueStoreEntry>
- размер
пустота
Возвращает количество записей в хранилище, соответствующих
queueName
.Функция
size
выглядит так:() => {...}
- возвращает
Обещание<число>
- unshiftEntry
пустота
Добавьте запись первой в очереди.
Функция
unshiftEntry
выглядит так:(entry: UnidentifiedQueueStoreEntry) => {...}
- вход
НеопознанныйQueueStoreEntry
- возвращает
Обещание<void>
StorableRequest
Класс, упрощающий сериализацию и десериализацию запросов, чтобы их можно было хранить в IndexedDB.
Большинству разработчиков не потребуется прямой доступ к этому классу; он доступен для расширенных случаев использования.
Характеристики
- конструктор
пустота
Принимает объект данных запроса, который можно использовать для создания
Request
, но также можно хранить в IndexedDB.Функция
constructor
выглядит так:(requestData: RequestData) => {...}
- запрос данных
ЗапросДанные
Объект данных запроса, включающий
url
и все соответствующие свойства [requestInit]https://fetch.spec.whatwg.org/#requestinit
.
- возвращает
- клонировать
пустота
Создает и возвращает глубокую копию экземпляра.
Функция
clone
выглядит так:() => {...}
- возвращает
- toObject
пустота
Возвращает глубокую копию объекта экземпляра
_requestData
.Функция
toObject
выглядит так:() => {...}
- возвращает
ЗапросДанные
- toRequest
пустота
Преобразует этот экземпляр в запрос.
Функция
toRequest
выглядит так:() => {...}
- возвращает
Запрос
- из запроса
пустота
Преобразует объект Request в простой объект, который можно структурировать, клонировать или преобразовать в строку JSON.
Функция
fromRequest
выглядит так:(request: Request) => {...}
- запрос
Запрос
- возвращает
Обещание < StorableRequest >