web-dev-qa-db-fra.com

Accès à distance par un employé Web

Je deviens fou et j'ai besoin de votre aide. Je travaille sur un projet de serviceworker et je suis confronté à un problème javascript. J'ai deux fichiers principaux. Le fichier server.html dans lequel j'appelle le fichier service-worker.js externe à la ligne 52. Voici monserver.htmlfile

<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>

et voici le fichier 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;
});

Dans la dernière ligne, je voudrais insérer le message reçu dans le div "talker". Mais j'obtiens toujours l'erreurservice-worker.js: 17 Uncaught ReferenceError: le document n'est pas défini

J'ai pris soin de charger le fichier js une fois le document chargé. Maintenant je ne sais pas ce que je fais mal. Merci. 

11
Raphael

Les employés de service - les travailleurs Web en général - n’ont aucun accès direct au DOM. Demandez au travailleur de publier les informations sur le thread principal et de laisser le code dans le thread principal mettre à jour le DOM, le cas échéant. Le modèle de lecture de JavaScript sur les navigateurs est qu’il n’ya qu’un seul thread principal de l’interface utilisateur (celui par défaut sur lequel le code de la page est exécuté), qui peut accéder au DOM. Les autres en sont exclus.

Cette page et cette page les deux parlent de la messagerie entre les prestataires de services et les clients. Voici un exemple très simple:

Script dans la page de chargement du service worker:

(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);
            });
    }
})();

Et en service-worker.js:

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

Cela repose sur event.source, qui est pris en charge par les versions actuelles de Chrome et Firefox.

Sinon, au lieu d'utiliser event.source, vous pouvez envoyer un message à plusieurs clients d'un agent de service à l'aide de self.clients.matchAll; à nouveau dans service-worker.js:

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

matchAll accepte certains options de filtrage .


Vous avez dit que vous aviez du mal à le faire fonctionner. Voici une version complète de ce qui fonctionne pour moi dans Chrome et Firefox:

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);
    }));
});

Comme vous pouvez le constater, c’est la version qui utilise self.clients.matchAll, avec la version commentée event.source au-dessus.

Si j'exécute cela dans deux fenêtres, chaque rafraîchissement de chaque fenêtre envoie un message aux autres fenêtres (parce que j'utilise self.clients.matchAll...).

22
T.J. Crowder

L'agent de service est basé sur une base asynchrone et, selon l'article, vous ne pouvez pas accéder au DOM en utilisant le service pour plus d'informations, lisez la suite https://developers.google.com/web/fundamentals/primers/service-workers/

0
Mohit Shukla