2016-06-08 12 views
5

Ich bin verrückt und brauche deine Hilfe. Ich arbeite an einem Servicearbeiter-Projekt und ich habe es mit einem Javascript-Problem zu tun. Ich habe zwei Hauptdateien. Die server.html Datei, in der ich die externe service-worker.js Datei in Zeile 52 aufrufen. Hier ist meine server.html DateiZugriff dom von Web Worker

<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 Service-worker.js Datei

// 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 würde Ich mag die empfangene Nachricht in den div einfügen " Redner ". Aber ich bekomme immer die Fehler Service-worker.js: 17 Uncaught Reference: Dokument ist nicht definiert

Ich kümmere mich, dass ich die js-Datei laden, nachdem das Dokument geladen wird. Jetzt weiß ich nicht, was ich falsch mache. Danke.

+6

-Code in einem Servicemitarbeiter keinen Zugang zu einem Dokument lesen gearbeitet. – Pointy

+0

Was ist Ihr Ziel bei der Verwendung eines Service-Arbeiters? Im Gegensatz zu einem geteilten Arbeiter oder nur einem Arbeiter? –

Antwort

15

Servicemitarbeiter   — Web-Mitarbeiter im Allgemeinen   — haben keinen direkten Zugriff auf das DOM überhaupt. Lassen Sie den Mitarbeiter stattdessen die Informationen im Hauptthread posten, und lassen Sie den Code im Hauptthread das DOM entsprechend aktualisieren. Das Thading-Modell für JavaScript in Browsern besteht darin, dass es nur einen Haupt-UI-Thread gibt (den Standard, auf dem Ihr In-Page-Code ausgeführt wird), der auf das DOM zugreifen kann. Die anderen sind davon abgeschottet.

This page und this page beide sprechen über Messaging zwischen Service-Mitarbeitern und Kunden. Hier ist ein wirklich einfaches Beispiel:

Script in der das Laden der Seite der Servicemitarbeiter:

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

Das auf event.source beruht, die von den aktuellen Versionen von Chrome unterstützt wird und Firefox.

Alternativ können Sie anstelle von event.source eine Nachricht an mehrere Clients eines Service-Mitarbeiters mit self.clients.matchAll 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 einige filtering options akzeptiert.


Sie haben gesagt, Sie haben Probleme, es zur Arbeit zu bringen.Hier ist eine vollständige Version von dem, was für mich in Chrome und Firefox 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 können, das ist die Version mit self.clients.matchAll, mit dem kommentierten aus event.source Version darüber.

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

+0

'Sie können das DOM nicht direkt von einem Worker aus bearbeiten 'von https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers –

+0

Kann ein Service-Mitarbeiter sein (im Gegensatz zu einem Web Arbeiter) sogar Nachrichten posten? – Pointy

+0

@ T.J. Crowder: Können Sie mir ein Beispiel geben, wie Sie die Konsolennachricht von der service-worker.js zur dom-Datei (server.html) bringen können? – Raphael

0

Service-Arbeiter auf asynchrone Basis und nach dem Artikel, den Sie nicht der DOM-Service für mehr Informationen zugreifen können, auf https://developers.google.com/web/fundamentals/primers/service-workers/

+0

Während dieser Link die Frage beantworten kann, werden Link Only-Antworten auf Stack Overflow abgeraten. Sie können diese Antwort verbessern, indem Sie wichtige Teile des Links in Ihre Antwort einfügen. Dadurch wird sichergestellt, dass Ihre Antwort immer noch eine Antwort ist geändert oder entfernt :) – WhatsThePoint