wake-up-neo.net

Greifen Sie von Web Worker auf Dom zu

Ich werde verrückt und brauche deine Hilfe. Ich arbeite an einem Service-Projekt und beschäftige mich mit einem Javascript-Problem. Ich habe zwei Hauptdateien. Die server.html-Datei, in der ich die externe service-worker.js-Datei in der Zeile 52____ anrufe. Hier ist meineserver.html-Datei

<body>
    <div class="container"> 
        <h1>PRESENTER</h1>
        <div id="nicky">Nickname: <span id="nickname"></span></div>
        <form id="form-nick" name="form-nick" method="post" action="">
            <div class="formelement">
                <label name="labelnick" for="nick">Nickname:</label>
                <input type="text" id="nick" name="nick">
                <button type="submit">OK</button>
            </div>
        </form><br /><br />

        <h1>--></h1><div id="talker"></div>

        <button type="button" class="button blue" id="blue-display" disabled></button><br />

        <button type="button" class="button red" disabled></button><br />

        <button type="button" class="button lightblue" disabled></button>
    </div> <!-- container -->


    <script type="text/javascript">
        $(document).ready(function() {
            console.log("jquery ready function");

            $('#nick').focus();

            $('#form-nick').submit(function(){
                var form = $('#form-nick');
                var data = form.serialize();
                $.post('nicky.php', data, function(response) {
                    if (response) {
                        $('#nicky').show();
                        $('#nickname').text(response);
                        $('#form-nick').hide();
                        $('.blue, .red, .lightblue').fadeIn(100);

                        if('serviceWorker' in navigator){
                            // Register service worker
                            navigator.serviceWorker.register('service-worker.js').then(function(reg){
                                console.log("SW registration succeeded. Scope is "+reg.scope);

                            }).catch(function(err){
                                console.error("SW registration failed with error "+err);
                            });
                        }
                    } else {

                    }
                });
                return false;           
            });       
        });
    </script>
</body>

und hier ist die Datei service-worker.js

// Install Service Worker
self.addEventListener('install', function(event){
    console.log('>> sw installed!');
});
// Service Worker Active
self.addEventListener('activate', function(event){
    console.log('>> sw activated!');
});
// Service Worker reveives message
self.addEventListener('message', function(event){
    console.log(event.data);
    send_message_to_all_clients(event.data);
    document.getElementById("talker").innerHTML = event.data;
});

In der letzten Zeile möchte ich die empfangene Nachricht im div "talker" einfügen. Ich erhalte jedoch immer den Fehlerservice-worker.js: 17 Nicht abgefragter ReferenceError: Dokument ist nicht definiert

Ich habe darauf geachtet, dass ich die js-Datei nach dem Laden des Dokuments lade. Nun weiß ich nicht was ich falsch mache. Vielen Dank. 

11
Raphael

Service-Mitarbeiter - Web-Worker im Allgemeinen - haben überhaupt keinen direkten Zugriff auf das DOM. Lassen Sie den Arbeiter stattdessen die Informationen in den Haupt-Thread buchen und den DOM durch Code im Haupt-Thread entsprechend aktualisieren. Das führende Modell für JavaScript in Browsern ist, dass es nur einen Haupt-UI-Thread gibt (den Standard-Thread, auf dem Ihr In-Page-Code ausgeführt wird), der auf das DOM zugreifen kann. Die anderen sind davon abgeschottet.

Diese Seite und diese Seite sprechen beide über die Nachrichtenübermittlung zwischen Servicemitarbeitern und Kunden. Hier ist ein wirklich einfaches Beispiel:

Skript auf der Seite, die den Service Worker lädt:

(function() {
    "use strict";

    if (!navigator.serviceWorker || !navigator.serviceWorker.register) {
        console.log("This browser doesn't support service workers");
        return;
    }

    // Listen to messages from service workers.
    navigator.serviceWorker.addEventListener('message', function(event) {
        console.log("Got reply from service worker: " + event.data);
    });

    // Are we being controlled?
    if (navigator.serviceWorker.controller) {
        // Yes, send our controller a message.
        console.log("Sending 'hi' to controller");
        navigator.serviceWorker.controller.postMessage("hi");
    } else {
        // No, register a service worker to control pages like us.
        // Note that it won't control this instance of this page, it only takes effect
        // for pages in its scope loaded *after* it's installed.
        navigator.serviceWorker.register("service-worker.js")
            .then(function(registration) {
                console.log("Service worker registered, scope: " + registration.scope);
                console.log("Refresh the page to talk to it.");
                // If we want to, we might do `location.reload();` so that we'd be controlled by it
            })
            .catch(function(error) {
                console.log("Service worker registration failed: " + error.message);
            });
    }
})();

Und in service-worker.js:

self.addEventListener("message", function(event) {
    event.source.postMessage("Responding to " + event.data);
});

Dies basiert auf event.source, das von den aktuellen Versionen von Chrome und Firefox unterstützt wird.

Anstatt event.source zu verwenden, können Sie alternativ eine Nachricht mit self.clients.matchAll an mehrere Kunden eines Servicearbeiters senden. wieder in service-worker.js:

self.addEventListener("message", function(event) {
    self.clients.matchAll().then(all => all.forEach(client => {
        client.postMessage("Responding to " + event.data);
    }));
});

matchAll akzeptiert einige Filteroptionen .


Du hast gesagt, du hast Probleme damit, dass es funktioniert. Hier ist eine vollständige Version dessen, was in Chrome und Firefox für mich funktioniert:

service-worker.html:

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Service Worker</title>
</head>
<body>
(Look in the console.)
<script>
(function() {
    "use strict";

    if (!navigator.serviceWorker || !navigator.serviceWorker.register) {
        console.log("This browser doesn't support service workers");
        return;
    }

    // Listen to messages from service workers.
    navigator.serviceWorker.addEventListener('message', function(event) {
        console.log("Got reply from service worker: " + event.data);
    });

    // Are we being controlled?
    if (navigator.serviceWorker.controller) {
        // Yes, send our controller a message.
        console.log("Sending 'hi' to controller");
        navigator.serviceWorker.controller.postMessage("hi");
    } else {
        // No, register a service worker to control pages like us.
        // Note that it won't control this instance of this page, it only takes effect
        // for pages in its scope loaded *after* it's installed.
        navigator.serviceWorker.register("service-worker.js")
            .then(function(registration) {
                console.log("Service worker registered, scope: " + registration.scope);
                console.log("Refresh the page to talk to it.");
                // If we want to, we might do `location.reload();` so that we'd be controlled by it
            })
            .catch(function(error) {
                console.log("Service worker registration failed: " + error.message);
            });
    }
})();
</script>
</body>
</html>

service-worker.js:

self.addEventListener("message", function(event) {
    //event.source.postMessage("Responding to " + event.data);
    self.clients.matchAll().then(all => all.forEach(client => {
        client.postMessage("Responding to " + event.data);
    }));
});

Wie Sie sehen, ist dies die Version, die self.clients.matchAll verwendet, darüber steht die auskommentierte event.source-Version.

Wenn ich das in zwei Fenstern starte, sendet jede Aktualisierung jedes Fensters eine Nachricht an die anderen Fenster (weil ich self.clients.matchAll... verwende).

22
T.J. Crowder

Der Servicemitarbeiter basiert auf asynchron. Gemäß dem Artikel können Sie nicht auf das DOM zugreifen, indem Sie den Dienst verwenden. Weitere Informationen finden Sie unter https://developers.google.com/web/fundamentals/primers/service-workers) /

0
Mohit Shukla