Möglichkeiten zum Synchronisieren von Browser-Registerkarten



Vor langer Zeit schien es in einer fernen Galaxie eine Aufgabe zu geben, Browser-Registerkarten für einen Web-Player wie VK zu synchronisieren: Es war notwendig, den Datenaustausch zwischen Registerkarten zu organisieren, ihre Anzahl zu verfolgen und einigen von ihnen Aufgaben zuzuweisen. Die gesamte Implementierung musste auf dem Client durchgeführt werden. Viele Informationen wurden gesammelt und in einen ganzen Artikel geschrieben.

Im Folgenden werde ich verschiedene Möglichkeiten zur Lösung solcher Probleme beschreiben.

Betrachten Sie die beliebtesten Möglichkeiten zum Synchronisieren von Browser-Registerkarten in der Reihenfolge zunehmender Komplexität.

Lokaler Speicher


localStorage - Lokaler Speicher, eine Eigenschaft des Fensterobjekts, ermöglicht den Zugriff auf das lokale Speicherobjekt . Es kann Daten zwischen Benutzersitzungen speichern. Es gibt eine ähnliche Eigenschaft - sessionStorage , aber es werden nur Daten für die Dauer der Seitensitzung gespeichert.
Daten werden mit der setItem- Methode zum Speicher hinzugefügt .

localStorage.setItem('key', 'value'); 

Das Speicherereignis ist ideal zum Synchronisieren von Daten zwischen Registerkarten. Es wird generiert, wenn sich der Wert des Elements localStorage oder sessionStorage ändert.

 window.addEventListener('storage', function(event) { console.log(event.key); }); 

Das Ereignis funktioniert nicht auf der Registerkarte, die Änderungen vornimmt, sondern wird auf den verbleibenden Registerkarten der Domäne im Browser ausgelöst.

Generierung von Speicherereignissen

Browser haben unterschiedliche Speicherebenen für localStorage und sessionStorage:

  • Chrome, FireFox und Opera ~ 5 MB.
  • IE ~ 4,8 MB.
  • iOS Safari, OS X Safari ~ 2,5 MB.
  • Android ~ 5 MB.

Unter den Mängeln kann man feststellen - die Menge an Browserspeicher, und wenn es voll ist, wird ein neues Objekt nicht aufgezeichnet.
Die Methode funktioniert in allen Browsern außer Opera mini .

Nachricht posten


postMessage ist eine Methode, mit der Sie domänenübergreifende Anforderungen sicher senden, dh miteinander an Windows und Iframes aus verschiedenen Domänen kommunizieren können.
Es ist sehr praktisch für die Interaktion von externen Widgets und Diensten, die über iframe von der Hauptseite aus verbunden sind.
Nachrichtenübertragung:

 const win = window.frames.target; win.postMessage('send message', 'http://javascript.ru'); 

Die übertragenen Daten können beliebige Objekte sein, die das Klonen unterstützen (Zeichenfolge, Objekt, Array, Karte, Datum ...). Der IE unterstützt jedoch nur Zeichenfolgen.

URL zeigt an, dass nur Fenster von dieser Quelle Nachrichten empfangen können.
Um Nachrichten zu empfangen, muss das Fenster das Ereignis onmessage abonnieren.

 window.addEventListener('message', function(event) { if (event.origin != 'http://javascript.ru') { return; } console.log(event.data); }); 

Jedes Fenster kann auf diese Methode zugreifen, um eine Nachricht an sie zu senden, unabhängig vom Speicherort des Dokuments im Fenster. Überprüfen Sie daher unbedingt den Ursprung.

Im IE funktioniert die postMessage- Oberfläche nur mit iframes und nicht zwischen Registerkarten und Fenstern.

Broadcast Channel API


Die Broadcast Channel API bietet eine einfache Verknüpfung zwischen dem Anzeigekontext (Fenster, Registerkarten). Das BroadcastChannel- Objekt erstellt einen gemeinsamen Kanal, über den Sie alle an ihn gesendeten Nachrichten empfangen können. Registerkarten, Fenster und Iframes können den Kanal abonnieren und eine Verbindung mit ihm herstellen.

 const bc = new BroadcastChannel('test_channel'); 

Die postMessage-Methode sendet eine Nachricht an den Kanal. Das Argument ist ein Typ, der das Klonen unterstützt.

 bc.postMessage('This is a test message.'); 

Wenn eine Nachricht veröffentlicht wird, wird ein Nachrichtenereignis an jedes mit diesem Kanal verbundene Objekt gesendet.

 bc.addEventListener('message', function (e) { console.log(e); }) 


Veröffentlichen Sie eine Nachricht in einem Kanal für verschiedene Kontexte.

Die API ist ziemlich einfach und kann als einfacher Nachrichtenbus betrachtet werden. Die Methode hat jedoch einen schwerwiegenden Nachteil: Safari und IE werden nicht unterstützt.

Auf den ersten Blick finden Sie mehrere ähnliche Methoden zur Datenübertragung (z. B. MessageChannel, WebSocket), die jedoch jeweils einem bestimmten Zweck dienen - dem Vergleich .

Web-Worker


Dies ist ein Mechanismus, mit dem ein Skript in einem Hintergrundthread ausgeführt werden kann, der vom Hauptthread einer Webanwendung getrennt ist. Es wird mithilfe von JS-Dateien implementiert, die mithilfe einer asynchronen HTTP-Anforderung auf der Seite enthalten sind.

Mitarbeiter eignen sich hervorragend für umfangreiche Computeroperationen, ohne die Benutzeroberfläche zu verlangsamen.
Bei der Synchronisierung können jedoch nur zwei Arten von Arbeitnehmern helfen.

Geteilter Arbeiter


Dies ist eine spezielle Art von Worker, auf die über verschiedene Browserkontexte zugegriffen werden kann. Schreiben wir eine gemeinsam genutzte js-Datei für Registerkarten, zum Beispiel shared-worker.js.

 const worker = new SharedWorker('shared-worker.js'); 

Jede Registerkarte kann über worker.port mit dem Worker kommunizieren. Das Worker-Skript hat auch Zugriff auf seine Ports. Jedes Mal, wenn die Registerkarte eine Verbindung zum Worker herstellt, wird das Verbindungsereignis im Skript ausgelöst.

 // shared-worker.js const connections = []; onconnect = function(e) { const port = e.ports[0]; connections.push(port); }; 

Die postMessage-Methode wurde erstellt, um Registerkarten an einen freigegebenen Mitarbeiter zu senden.

 worker.port.postMessage('test message'); 

Sie können Arbeitsdaten mithilfe des Nachrichtenereignisses abrufen.

 worker.port.onmessage = function (e) { console.log(e.data); }; 

In der SharedWorker-API gibt es ein Verbindungsereignis, aber es gibt kein Verbindungsereignis. Daher können Daten in geschlossenen Registerkarten nicht selbst bereinigt werden. Sie werden weiterhin als offen betrachtet. Dies führt nicht zu Fehlern, kann jedoch als Fehler- oder Funktions-API angesehen werden.

Funktioniert nur in Chrome und FF .

Servicemitarbeiter


Dies ist ein ereignisgesteuerter Mitarbeiter, der Netzwerkanforderungen überwachen, abfangen, ändern und zwischenspeichern kann.
Arbeitnehmerregistrierung:

 if ('serviceWorker' in navigator) { navigator.serviceWorker.register('service-worker.js') .then(function() { return navigator.serviceWorker.ready; }) .catch(function(error) { console.error('registration error : ', error); }); } 

Mithilfe des Nachrichtenereignisses können die Registerkarten Daten aus der Worker-JS-Datei empfangen, und die Funktion syncTabState wird zum Verarbeiten der Nachricht verwendet.

 self.addEventListener('message', function(e){ const data = e.data; const tabId = e.source.id self.syncTabState(data, tabId); }); 

Die Funktion sendTabState dient zum Senden von Nachrichten an Registerkarten.

 self.sendTabState = function(client, data){ client.postMessage(data); } 

Detaillierte Verwendung und viele Beispiele hier .

Alle Web-Worker haben keinen Zugriff auf die Fenster- und Dokumentobjekte.

Service Worker funktioniert nicht in IE und Opera mini .

Synchronisationsbibliotheken


Dies ist ein Weg für diejenigen, die nicht Fahrrad fahren möchten und bereit sind, vorhandene Lösungen in Betracht zu ziehen.


Ihr Nachteil ist, dass die Bibliotheken meist universell sind und daher nicht immer für enge Lösungen geeignet sind.

Zusammenfassung


Lassen Sie uns zusammenfassend die Methoden der Browserunterstützung visuell vergleichen.


Verwenden Sie LocalStorage, BroadcastChannel und PostMessage für einfache Fälle, in denen Sie eine Nachricht an möglicherweise mehrere Fenster / Registerkarten oder Iframes senden müssen.

Shared Worker und Service Worker sind die am besten geeigneten Lösungen für die Verwaltung gemeinsam genutzter Statussperren und gemeinsam genutzter Dateien.

Für die Aufgabe mit dem Web-Player wurde LocalStorage ausgewählt, da der IE unterstützt wird.
Ich hoffe, dieser Artikel hat Ihnen bei der Auswahl der richtigen Synchronisationsmethode geholfen.

Ich danke dem Posterteam für ihre Hilfe und Unterstützung!

Gebrauchte Artikel:

Source: https://habr.com/ru/post/de422545/


All Articles