In einigen Fällen muss eine Webanwendung einen zweiseitigen Kommunikationskanal zwischen dem und den Service Worker.
Beispiel: In einer Podcast-PWA könnte eine Funktion entwickelt werden, mit der Nutzer Folgen für zur Offlinenutzung und Service Worker, um die Seite regelmäßig über den Fortschritt zu informieren, damit die Hauptseite Thread die UI aktualisieren kann.
In diesem Leitfaden werden die verschiedenen Möglichkeiten zur Implementierung einer wechselseitigen Kommunikation zwischen das Fenster und der Service Worker-Kontext durch Untersuchung verschiedene APIs, die Workbox-Bibliothek sowie einige fortgeschrittene Fälle.
<ph type="x-smartling-placeholder">Workbox verwenden
workbox-window
besteht aus einer Reihe von
der Workbox-Bibliothek enthalten,
die im Fensterkontext ausgeführt werden soll. Die Workbox
bietet eine messageSW()
-Methode, um eine Nachricht an den registrierten Service Worker der Instanz zu senden, und
auf eine Antwort warten.
Mit dem folgenden Seitencode wird eine neue Workbox
-Instanz erstellt und eine Nachricht an den Service Worker gesendet
erhalten Sie die Version:
const wb = new Workbox('/sw.js');
wb.register();
const swVersion = await wb.messageSW({type: 'GET_VERSION'});
console.log('Service Worker version:', swVersion);
Der Service Worker implementiert am anderen Ende einen Nachrichten-Listener und antwortet dem registrierten Service Worker:
const SW_VERSION = '1.0.0';
self.addEventListener('message', (event) => {
if (event.data.type === 'GET_VERSION') {
event.ports[0].postMessage(SW_VERSION);
}
});
Intern verwendet die Bibliothek eine Browser-API, die im nächsten Abschnitt erläutert wird: Nachricht Kanal, abstrahiert aber viele Implementierungsdetails, was eine einfachere Nutzung ermöglicht und gleichzeitig den umfassenden Browser diese API unterstützt.
Browser-APIs verwenden
Wenn die Workbox-Bibliothek für Ihre Anforderungen nicht ausreicht, stehen mehrere untergeordnete APIs zur Verfügung. Implementieren einer wechselseitigen Kommunikation zwischen Seiten und Service Workern. Sie haben einige Ähnlichkeiten und Unterschiede:
Gemeinsamkeiten:
- In allen Fällen beginnt die Kommunikation an einem Ende über die
postMessage()
-Schnittstelle und wird empfangen. indem Sie einenmessage
-Handler implementieren. - In der Praxis können mit allen verfügbaren APIs dieselben Anwendungsfälle implementiert werden, aber einige davon. die Entwicklung in einigen Szenarien vereinfachen.
Unterschiede:
- Sie identifizieren die andere Seite der Kommunikation auf unterschiedliche Weise: Einige nutzen ein expliziter Verweis auf den anderen Kontext, während andere implizit über einen Proxy kommunizieren können -Objekt, das auf jeder Seite instanziiert ist.
- Welche Browser unterstützt werden, hängt von der jeweiligen Situation ab.
Broadcast-Channel-API
Die Broadcast Channel API ermöglicht die grundlegende Kommunikation zwischen Browserkontexten über BroadcastChannel Objekte.
Zur Implementierung muss jeder Kontext zuerst ein BroadcastChannel
-Objekt mit derselben ID instanziieren
und Nachrichten senden und empfangen:
const broadcast = new BroadcastChannel('channel-123');
Das BroadcastChannel-Objekt stellt eine postMessage()
-Schnittstelle bereit, über die eine Nachricht an einen beliebigen Hörer gesendet werden kann.
Kontext:
//send message
broadcast.postMessage({ type: 'MSG_ID', });
Jeder Browserkontext kann Nachrichten über die Methode onmessage
von BroadcastChannel
abhören.
-Objekt enthält:
//listen to messages
broadcast.onmessage = (event) => {
if (event.data && event.data.type === 'MSG_ID') {
//process message...
}
};
Es gibt keinen expliziten Verweis auf einen bestimmten Kontext, daher ist keine auf den Service Worker oder einen bestimmten Client verweisen.
Der Nachteil ist, dass die API derzeit Unterstützung von Chrome, Firefox und Edge, aber andere Browser wie Safari unterstützen es nicht. .
Client-API
Mit der Client API können Sie ein
Verweis auf alle WindowClient
-Objekte für die aktiven Tabs, die der Service Worker steuert
Da die Seite von einem einzelnen Service Worker gesteuert wird, überwacht er den Traffic und sendet Nachrichten an den
aktiven Service Worker direkt über die serviceWorker
-Schnittstelle:
//send message
navigator.serviceWorker.controller.postMessage({
type: 'MSG_ID',
});
//listen to messages
navigator.serviceWorker.onmessage = (event) => {
if (event.data && event.data.type === 'MSG_ID') {
//process response
}
};
In ähnlicher Weise überwacht der Service Worker Nachrichten, indem er einen onmessage
-Listener implementiert:
//listen to messages
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'MSG_ID') {
//Process message
}
});
Für die Rückmeldung mit einem seiner Clients erhält der Service Worker ein Array von
WindowClient
-Objekten hinzu, indem Sie Folgendes ausführen:
Methoden wie
Clients.matchAll()
und
Clients.get()
Dann kann es
postMessage()
einer davon:
//Obtain an array of Window client objects
self.clients.matchAll(options).then(function (clients) {
if (clients && clients.length) {
//Respond to last focused tab
clients[0].postMessage({type: 'MSG_ID'});
}
});
Client API
ist eine gute Option, um einfach mit allen aktiven Tabs eines Service Workers zu kommunizieren
relativ einfach erklären. Das API wird von allen wichtigen
Browser,
Möglicherweise sind jedoch nicht alle Methoden verfügbar. Überprüfen Sie daher die Browserunterstützung,
auf Ihrer Website implementieren.
Kanal für Nachrichten
Message Channel erfordert Definition und Übergabe eines Ports von einem Kontext an einen anderen, um eine Zwei-Wege-Kommunikation einzurichten Kanal.
Zum Initialisieren des Channels instanziiert die Seite ein MessageChannel
-Objekt und verwendet es
, um einen Port an den registrierten Service Worker zu senden. Die Seite implementiert außerdem einen onmessage
-Listener auf
Nachrichten aus dem anderen Kontext empfangen:
const messageChannel = new MessageChannel();
//Init port
navigator.serviceWorker.controller.postMessage({type: 'PORT_INITIALIZATION'}, [
messageChannel.port2,
]);
//Listen to messages
messageChannel.port1.onmessage = (event) => {
// Process message
};
Der Service Worker empfängt den Port, speichert einen Verweis darauf und sendet damit eine Nachricht an den anderen Port Seite:
let communicationPort;
//Save reference to port
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'PORT_INITIALIZATION') {
communicationPort = event.ports[0];
}
});
//Send messages
communicationPort.postMessage({type: 'MSG_ID'});
MessageChannel
wird derzeit von allen großen
Browser.
Erweiterte APIs: Hintergrundsynchronisierung und Hintergrundabruf
In diesem Leitfaden haben wir Methoden zur Implementierung von Zwei-Wege-Kommunikationstechniken für relativ einfache Fälle wie das Übergeben einer Zeichenfolgennachricht, die den auszuführenden Vorgang beschreibt, oder eine Liste von URLs von einem Kontext in den anderen im Cache zu speichern. In diesem Abschnitt befassen wir uns mit zwei APIs, Mangelnde Internetverbindung und lange Downloads.
Hintergrundsynchronisierung
Eine Chat-App möchte möglicherweise sicherstellen, dass Nachrichten nicht aufgrund schlechter Verbindung verloren gehen. Die Mit der Background Sync API können Sie: zu verschieben, wenn der Nutzer eine stabile Verbindung hat. Dies ist nützlich, um sicherzustellen, was der Nutzer senden möchte, tatsächlich gesendet wird.
Anstelle der postMessage()
-Schnittstelle registriert die Seite eine sync
:
navigator.serviceWorker.ready.then(function (swRegistration) {
return swRegistration.sync.register('myFirstSync');
});
Der Service Worker wartet dann auf das Ereignis sync
, um die Nachricht zu verarbeiten:
self.addEventListener('sync', function (event) {
if (event.tag == 'myFirstSync') {
event.waitUntil(doSomeStuff());
}
});
Die Funktion doSomeStuff()
sollte ein Versprechen zurückgeben, das den Erfolg/Scheitern der Funktion angibt.
was wir tun wollen. Wenn sie erfüllt ist, ist die Synchronisierung abgeschlossen. Wenn er fehlschlägt, wird eine weitere Synchronisierung geplant,
noch einmal versuchen. Synchronisierungswiederholungen warten auch auf eine Verbindung und verwenden einen exponentiellen Backoff.
Sobald der Vorgang abgeschlossen ist, kann der Service Worker mit der Seite kommunizieren, um die UI mithilfe einer der zuvor erforschten Kommunikations-APIs aktualisieren.
Die Google-Suche verwendet die Hintergrundsynchronisierung, um fehlgeschlagene Suchanfragen aufgrund einer schlechten Verbindung beizubehalten, und es erneut versuchen. wenn die Nutzenden online sind. Sobald der Vorgang ausgeführt wurde, wird das Ergebnis an über eine Web-Push-Benachrichtigung:
<ph type="x-smartling-placeholder">Hintergrundabruf
Bei relativ kurzen Arbeitsschritten wie dem Senden einer Nachricht oder einer Liste von URLs, die im Cache gespeichert werden sollen, sind eine gute Wahl. Wenn die Aufgabe zu lange dauert, beendet der Browser den Dienst Andernfalls stellt dies eine Gefahr für Datenschutz und Akku des Nutzers dar.
Die Background Fetch API ermöglicht es Ihnen, einen Service Worker einer langen Aufgabe zu überlassen, z. B. dem Herunterladen von Filmen, Podcasts oder Levels. eines Spiels.
Wenn Sie von der Seite aus mit dem Service Worker kommunizieren möchten, verwenden Sie backgroundFetch.fetch
statt
postMessage()
:
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.fetch(
'my-fetch',
['/ep-5.mp3', 'ep-5-artwork.jpg'],
{
title: 'Episode 5: Interesting things.',
icons: [
{
sizes: '300x300',
src: '/ep-5-icon.png',
type: 'image/png',
},
],
downloadTotal: 60 * 1024 * 1024,
},
);
});
Mit dem Objekt BackgroundFetchRegistration
kann die Seite auf das progress
-Ereignis warten, dem folgt
Fortschritt des Downloads:
bgFetch.addEventListener('progress', () => {
// If we didn't provide a total, we can't provide a %.
if (!bgFetch.downloadTotal) return;
const percent = Math.round(
(bgFetch.downloaded / bgFetch.downloadTotal) * 100,
);
console.log(`Download progress: ${percent}%`);
});
Nächste Schritte
In diesem Leitfaden haben wir uns mit dem allgemeinsten Fall der Kommunikation zwischen Page und Service Workern befasst. (bidirektionale Kommunikation).
Häufig benötigt der eine nur einen Kontext, um mit dem anderen zu kommunizieren, ohne einen Antwort. In den folgenden Leitfäden erfahren Sie, wie Sie unidirektionale Techniken Ihre Seiten vom und zum Service Worker, zusammen mit Anwendungsfällen und Produktionsbeispielen:
- Leitfaden zum imperativen Caching: Service Worker von der Seite aus aufrufen, im Voraus im Cache speichern (z.B. beim Vorabruf).
- Broadcast-Updates: Die Seite wird vom Service Worker zur Information aufgerufen. über wichtige Updates (z. B. ist eine neue Version der Web-App verfügbar)