Сервисные работники: когда браузер снова синхронизируется? - PullRequest
0 голосов
/ 14 декабря 2018

Я создаю прогрессивное веб-приложение с помощью Google Workbox.Я настроил работника сервиса с помощью bgSync (в папке сборки), чтобы мои POST-запросы помещались в очередь и отправлялись на мою конечную точку, когда пользователь восстанавливает соединение, но когда именно происходит событие синхронизации?

В целях разработки я использую кнопку «Синхронизация», включенную в Chrome, как подробно описано в этом ответе: Как вручную запустить фоновую синхронизацию (для тестирования)? , но это вручную,Я хотел бы, чтобы запросы отправлялись на конечную точку, как только приложение вернется в оперативный режим, но когда я получаю соединение, мои запросы не отправляются, я должен вручную нажать кнопку «Синхронизировать», чтобы это произошло, и это делаетработать прекрасно, но пользователи не будут нажимать кнопку «Синхронизация» в реальном сценарии.

Точно, я хотел бы знать, есть ли способ, внутри моего работника службы, определить, когда приложениевернуться в онлайн и принудительно синхронизировать.Или узнать, когда произойдет синхронизация.Вот фрагмент кода для справки (с использованием Workbox 3.0.0):

const bgSyncPlugin = new workbox.backgroundSync.Plugin('myQueue', {
  callbacks: {
    requestWillEnqueue: (storableRequest) => {}, // I show a push notification indicating user is offline
    requestWillReplay: (storableRequest) => {},
    queueDidReplay: (storableRequestArray) => {} // If I get a response, I show a push notification
      }
   },
);

workbox.routing.registerRoute(
  "https://myapi.com/action",
  workbox.strategies.networkOnly({
    plugins: [bgSyncPlugin]
  }),
  'POST'
);

Ответы [ 2 ]

0 голосов
/ 23 мая 2019

Вы можете изменить период, в течение которого будут повторяться попытки, используя параметр maxRetentionTime, который принимает минуты в качестве значения.Например, если вы хотите повторить попытку в течение 2 дней, вы можете инициализировать очередь следующим образом:

const queue = new workbox.backgroundSync.Queue('requestsQueue', {
    maxRetentionTime: 48 * 60 //2 days
});

Конечно, если запрос в очереди будет выполнен успешно, он больше не будет повторяться.

Дополнительная информация в документах: https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.backgroundSync.Queue

0 голосов
/ 22 января 2019

Итак, на сегодняшний день фоновая синхронизация в Chrome пытается отправить запросы в очереди 3 раза (никогда не объяснялось в документации по рабочему ящику или фоновой синхронизации):

  • Первый раз: при запросефактически выполняется в первый раз, и браузер обнаруживает, что пользователь не имеет соединения, поэтому он помещает запрос в indexedDB.
  • Второй раз: ровно через 5 минут после первой попытки.
  • Третий раз: Ровно через 15 минут после первой попытки.

Если у пользователя нет соединения через 15 минут, то запросы просто застревают в indexedDB, пока новый запрос в очереди не попытается вытолкнуть остальные.Это не очень полезно в сценарии, когда мы ожидаем, что у пользователя не будет подключения к Интернету в течение нескольких часов.

Существуют планы (с 2016 года!) Реализовать PeriodicSync, который позволил бы разработчику выбирать, сколько раз и сколько времени потребуется браузеру для синхронизации, но он так и не был реализован, см .:https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/periodicSync

Я придумал неуклюжее решение, хотя, возможно, не самое лучшее, но оно делает то, что мне нужно.Существует событие синхронизации, которым мы можем манипулировать, чтобы повторить запросы, которые мы застряли в indexedDB.Мы должны использовать класс Workbox Queue вместо плагина.

// our service worker file
// we create a push notification function so the user knows when the requests are being synced

const notificate = (title, message) => {
    self.registration.showNotification(title, {
    body: message,
    icon: '/image.png',
    tag: 'service-worker'
 })
}

// let's create our queue
const queue = new workbox.backgroundSync.Queue('myQueue', {
   callbacks: {
       requestWillEnqueue: () => {
       notificate('You are offline! ?', 'Your request has been submitted to the Offline 
queue. The queue will sync with the server once you are back online.')
    }
});

// sync event handler
self.addEventListener("sync", (ev) => {
  queue.replayRequests().then((a) => {
    notificate('Syncing Application... ?', 'Any pending requests will be sent to the 
server.');
  }).catch(
    notificate('We could not submit your requests. ❌', 'Please hit the \'Sync Pending 
Requests\' button when you regain internet connection.')
    );
 });

Теперь внутри нашего файла представления HTML / React / Node мы можем сделать:

  // this will trigger our Sync event
  <button type="button" onClick={navigator.serviceWorker.ready.then(reg =>
      reg.sync.register('myEvent'))}>{'Sync Pending
  Requests'}</button>

Обратите внимание, что я создал HTMLкнопка, которая заставляет моего сервисного работника запускать queue.replayRequests (), поэтому функция фоновой синхронизации не происходит автоматически, мне нужно вручную нажать кнопку, чтобы это произошло.

...