Двунаправленная связь между клиентской страницей и сервисным работником - PullRequest
0 голосов
/ 03 апреля 2020

Имея приложение preact, сгенерированное preact-cli (использует workbox), моя цель - зарегистрировать обработчик событий 'message' на сервисном работнике, опубликовать сообщение из приложения и, наконец, получить ответ обратно.

Что-то вроде:

/* app.js */
navigator.serviceWorker.postMessage('marco');

const response = ? // get the response somehow
/* sw.js */
addEventListener('message', function (e) { return 'polo' });

У меня нет большого опыта работы с сервисными работниками, и есть много движущихся частей, которые меня смущают, как, например, рабочий бокс делает магию c на сервисном работнике, preact скрывает код, который регистрирует работника службы и обслуживающего персонала, который сложно отладить в целом.

Пока что я поместил файл sw.js в каталог src/ в соответствии с инструкциями preact-cli документы здесь: https://preactjs.com/cli/service-worker/

Я знаю, что должен подключить прослушиватель событий, но не могу найти документацию, для какого объекта это сделать.

1 Ответ

0 голосов
/ 07 апреля 2020

(Ни Workbox, ни Preact не имеют большого отношения к этому вопросу. Workbox позволяет вам использовать любой дополнительный код в вашем сервисном работнике, который вам нужен, и Preact должен также использовать его для вашего клиентского приложения.)

Страница этого примера демонстрирует отправку сообщения со страницы клиента сервисному работнику, а затем отвечает, используя MessageChannel. Соответствующий вспомогательный код, используемый на странице клиента, выглядит следующим образом:

function sendMessage(message) {
  return new Promise(function(resolve, reject) {
    const messageChannel = new MessageChannel();
    messageChannel.port1.onmessage = function(event) {
      // The response from the service worker is in event.data
      if (event.data.error) {
        reject(event.data.error);
      } else {
        resolve(event.data);
      }
    };

    navigator.serviceWorker.controller.postMessage(message,
      [messageChannel.port2]);
  });
}

А затем в своем работнике службы вы используете порт MessageChannel для ответа:

self.addEventListener('message', function(event) {
  // Your code here.

  event.ports[0].postMessage({
    error: // Set error if you want to indicate a failure.
    message: // This will show up as event.data.message.
  });
});

Вы можно также сделать то же самое, используя библиотеку Comlink для упрощения логики c.

...