Когда вы отправляете данные на веб-сервер, иногда запросы не выполняются. Это может быть связано с тем, что пользователь потерял соединение или сервер не работает; в любом случае вам часто захочется попробовать отправить запросы позже.
Новый 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 >