Möglichkeiten, Browser-Registerkarten zu synchronisieren



    Vor langer Zeit, in einer fernen Galaxie, schien es eine Aufgabe zu sein, Browser-Registerkarten für einen Web-Player wie VK zu synchronisieren: Es war notwendig, den Datenaustausch zwischen Registerkarten zu organisieren, deren Anzahl zu verfolgen und einigen von ihnen Aufgaben zuzuweisen. Alle Implementierungen mussten auf dem Client ausgeführt werden. Viele Informationen wurden gesammelt und im gesamten Artikel gesammelt.

    Im Folgenden werde ich verschiedene Wege beschreiben, um solche Probleme zu lösen.

    Berücksichtigen Sie die gängigsten Methoden zum Synchronisieren von Browser-Registerkarten in der Reihenfolge zunehmender Komplexität.

    Lokaler Speicher


    localStorage - local storage, eine Eigenschaft des window-Objekts, ermöglicht den Zugriff auf das lokale Speicherobjekt . Es kann Daten zwischen Benutzersitzungen speichern. Es gibt eine ähnliche Eigenschaft - sessionStorage , die jedoch nur während der Seitensitzung Daten speichert.
    Daten werden mithilfe der setItem- Methode zum Speicher hinzugefügt .

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

    Das Speicherereignis ist ideal zum Synchronisieren von Daten zwischen Registerkarten und 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 auf den anderen Registerkarten der Domäne im Browser.

    Ereigniserzeugung Speicher

    Browser haben verschiedene Ebenen von Speichervolumen für localstorage und session:

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

    Zu den Unzulänglichkeiten kann man feststellen, wie viel Speicherplatz der Browser hat und wenn er überläuft, dass ein neues Objekt nicht aufgezeichnet wird.
    Die Methode funktioniert in allen Browsern außer Opera mini .

    Nachricht posten


    postMessage ist eine Methode, mit der Sie sicher domänenübergreifende Anforderungen senden können, d. h. miteinander Fenster 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.
    Nachricht senden:

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

    Bei den übertragenen Daten kann es sich um ein beliebiges Objekt handeln, das das Klonen unterstützt (Zeichenfolge, Objekt, Array, Karte, Datum ...). IE unterstützt jedoch nur Strings.

    URL gibt an, dass nur Nachrichten aus dieser Quelle empfangen werden können.
    Um Nachrichten empfangen zu können, 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 ihm eine Nachricht zu senden, unabhängig von der Position des Dokuments im Fenster. Überprüfen Sie daher unbedingt den Ursprung.

    Die postMessage- Schnittstelle funktioniert im IE nur mit Iframes und funktioniert nicht zwischen Registerkarten und Fenstern.

    Broadcast Channel API


    Die Broadcast Channel API stellt eine einfache Verbindung zwischen dem Anzeigekontext (Fenster, Registerkarten) bereit. Das BroadcastChannel- Objekt erstellt einen freigegebenen Kanal, über den Sie alle an ihn gesendeten Nachrichten empfangen können. Registerkarten, Fenster und iframes können den Kanal abonnieren und mit ihm kommunizieren.

    const bc = new BroadcastChannel('test_channel');

    Die postMessage-Methode veröffentlicht die Nachricht im 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 Objekt gesendet, das mit diesem Kanal verbunden ist.

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


    Channel-Posting für verschiedene Kontexte.

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

    Auf den ersten Blick können Sie mehrere ähnliche Datentransfermethoden finden (z. B. MessageChannel, WebSocket), die jedoch jeweils einem bestimmten Zweck dienen - dem Vergleich .

    Web Workers


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

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

    Geteilter Arbeiter


    Dies ist ein spezieller Arbeitertyp, auf den von mehreren Browserkontexten aus zugegriffen werden kann. Schreiben wir die allgemeine 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 Arbeiterskript hat auch Zugriff auf seine Ports. Jedes Mal, wenn sich eine Registerkarte mit einem Worker verbindet, wird im Skript ein Verbindungsereignis ausgelöst.

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

    Die postMessage-Methode dient zum Senden von Registerkartendaten an einen allgemeinen Worker.

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

    Sie können die Daten vom Arbeiter über das Nachrichtenereignis erhalten.

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

    Die SharedWorker-API verfügt über ein Verbindungsereignis, es gibt jedoch kein Trennungsereignis. Daher können die Daten nicht in geschlossenen Registerkarten selbst gereinigt werden. Sie werden weiterhin als offen betrachtet. Dies führt nicht zu Fehlern, kann jedoch als Fehler- oder API-Funktion betrachtet werden.

    Funktioniert nur in Chrome und FF .

    Servicemitarbeiter


    Hierbei handelt es sich um einen ereignisgesteuerten Worker, der Netzwerkanforderungen überwachen, abfangen und ändern sowie im Cache speichern kann.
    Arbeiterregistrierung:

    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 Js-Datei des Arbeiters abrufen, und die Funktion syncTabState wird zur Verarbeitung der Nachricht verwendet.

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

    Die sendTabState-Funktion dient zum Senden von Nachrichten an Registerkarten.

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

    Ausführliche 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 .

    Bibliotheken synchronisieren


    Dies ist eine Möglichkeit für diejenigen, die nicht Fahrrad fahren möchten und bereit sind, bestehende Lösungen zu prüfen.


    Ihr Nachteil ist, dass Bibliotheken grundsätzlich universell sind und sich daher nicht immer für enge Lösungen eignen.

    Das Ergebnis


    Um das Endergebnis zusammenzufassen, vergleichen wir die Methoden für die Browserunterstützung visuell.


    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.

    Für die Verwaltung von gemeinsam genutzten Statussperren und gemeinsam genutzten Dateien ist Shared Workers und Service Worker die am besten geeignete Lösung.

    Und für die Aufgabe mit dem Webplayer wurde LocalStorage gewählt, da IE unterstützt wird.
    Ich hoffe, dass der Artikel Ihnen bei der Wahl der geeigneten Synchronisationsmethode geholfen hat.

    Ich danke dem Poster- Team für die Hilfe und Unterstützung!

    Verwendete Artikel:


    Jetzt auch beliebt: