HTML5 - Web Workers

Ich dachte mir, dass es doch keine schlechte Idee ist, euch mal einen kleinen Einblick in die Welt der Web Worker zu geben. Dazu gibt es ein kleines Beispiel und ein paar Worte, was denn diese Web Worker eigentlich sind.

In JavaScript war es immer ein Problem wenn es um Nebenläufigkeit ging. Die Sprache selbst ist eine Single-Threaded-Umgebung. Das bedeutet, dass alle möglichen Dinge im selben Script ablaufen und der Nutzer somit teilweise nichts anderes mehr auf der Seite machen konnte. Ich denke, viele von euch kennen dieses tolle Dialogfenster, oder?

NichtreagierendesScript

Mit Hilfe von setTimeout(), setIntervall(), XMLHttpRequest und EventHandlern konnte eine Nebenläufigkeit nachgeahmt werden. Diese Funktionen laufen zwar alle asynchron ab, sind blockierungsfrei aber dies bedeutet nicht, dass es auch parallel ist. Asynchrone Ereignisse werden verarbeitet, nachdem das aktuelle Ausführungsskript ausgesetzt wurde. In HTML5 gibt es nun eine tolle, bessere Lösung für solche Dinge.

Hier kommen nun die Web Worker ins Spiel. Ein Web Worker erzeugt Threads im Hintergrund der Webanwendung. Zum Beispiel ermöglicht es uns rechenintensive Scripts auszuführen ohne gleich unsere Benutzeroberfläche oder andere Scripts zu blockieren.

Ich zeige euch nur ein ganz kleines Beispiel. Für gewöhnlich benutzt man Web Worker nicht für solche Kleinigkeiten aber um zu verstehen, wie sie funktionieren, reicht auch ein kleines Script aus.

Da es sich um einen isolierten Thread handelt, bekommt der Worker seine eigene .js-Datei. Das Objekt des Workers selbst, erstellen wir trotzdem auf unserer Hauptseite. Was genau haben wir nun eigentlich vor? Ganz einfach, wir werden schnell zwei Buttons erstellen zum Starten und Stoppen des Workers. Drücken wir auf Start, so soll der Worker einen Counter starten. Ein Druck auf Stopp beendet ihn.

1 <!DOCTYPE html> 2 <html> 3 <body> 4 5 <p>Count numbers: <output id="result"></output></p> 6 <button onclick="startWorker()">Start Worker</button> 7 <button onclick="stopWorker()">Stop Worker</button> 8 <br><br> 9 10 <script> 11 12 var w; 13 14 function startWorker() { 15 if(typeof(Worker) !== "undefined") { 16 if(typeof(w) == "undefined") { 17 w = new Worker("../JS/WebWorkerBlog.js"); 18 } 19 w.onmessage = function(event) { 20 document.getElementById("result").innerHTML = event.data; 21 }; 22 } else { 23 document.getElementById("result").innerHTML = "Sorry! No Web Worker support."; 24 } 25 } 26 27 function stopWorker() { 28 w.terminate(); 29 w = undefined; 30 } 31 </script> 32 33 </body> 34 </html>

 

Was geschieht hier nun eigentlich? Drücken wir auf Start, überprüfen wir zunächst, ob unser Browser überhaupt in der Lage ist, Web Worker auszuführen. Unterstützt er sie nicht, bekommen wir die einfache Ausgabe: “Sorry! No Web Worker support.”

Wenn er sie unterstützt, überprüfen wir ob schon ein Worker existiert. Ist dies nicht der Fall, wird ein neuer erstellt. Dies geschieht ganz einfach über den Konstruktor des Workers mit der Pfadangabe der .js-Datei, in der unserer auszuführender Code liegt. Wie genau dieser Code aussieht, zeige ich gleich. Doch zunächst schauen wir erst mal weiter auf unsere Hauptseite. Im Code befindet sich ein EventHandler mit dem Namen “onmessage”. Der Worker wartet nach seiner Erstellung auf Nachrichten. Bekommt er eine, so reagiert der EventHanlder. In unserem Fall schreibt er die erhaltene Nachricht in den <output>-Tag mit der ID: “result”. Die Daten des Worker werden in “Event.data” gespeichert. Drücken wir auf Start, wird also solange(in diesem Beispiel jedenfalls) der Code ausgeführt, bis wir auf Stopp drücken. Damit wir wissen, was unserer Worker da überhaupt genau macht, werfen wir nun einen Blick in das entsprechende Script.

1 var i = 0; 2 3 function Counter() { 4 i = i + 1; 5 6 //Sendet eine Nachricht zurück an die HTML-Seite 7 8 postMessage(i); 9 setTimeout("Counter()", 1000); 10 } 11 12 Counter();

 

Sieht nicht sonderlich spektakulär aus, reicht aber. Hier befindet sich nun die Funktion unseres Workers. Wird er gestartet, führt er diese paar Zeilen Code aus. Alle 1000ms ruft er erneut die Methode “Counter” auf, und schickt das Ergebnis per “postMessage()” zurück an die Hauptseite. Jetzt springt in der Hauptseite der EventHandler an, nimmt die Nachricht entgegen und gibt sie uns im Browser aus. Der wichtigste Part hier ist die “postMessage()” Methode. Mit ihr werden Nachrichten ( oder auch JSON-Objekte) weitergeleitet. Wir können damit auch von der Hauptseite aus Nachrichten an die Worker-Datei senden und nicht nur von der Worker-Datei zur Hauptseite. Dazu brauchen wir nur das Worker-Objekt in der Hauptseite mit der “postMessage()” Methode ansprechen: “w.postMessage(“Hallo Worker”);”

Der Worker selbst wartet die ganze Zeit auf Nachrichten. Selbst dann, wenn das externe Script schon fertig ist. Um die Ressourcen freizugeben, muss der Worker beendet werden. Das können wir, wie in diesem Bespiel, über die Hauptseite per “w.terminate()” oder im Worker mit der “close()” Methode machen. Für gewöhnlich ist der Worker ganz beendet. Unsere Buttons würden nicht mehr funktionieren. Damit wir hier den Code aber erneut verwenden können, setzen wir ihn ganz einfach zurück. Das passiert in der “stopWorker()” Methode in der Hauptseite. Wir setzen unsere Variable “w” wieder auf “undefined” und können so den Code erneut nutzen.

Der Worker selbst kann aber nicht auf alle JavaScript-Funktionen zugreifen. Wir haben keinen Zugriff auf folgende Dinge: “window”-Objekt, “document”-Objekt, “parent”-Objekt.

Ich hoffe, der kleine Einblick war hilfreich für euch. Die Web Worker sind noch umfangreicher als hier dargestellt und das werden wir uns zu einem späteren Zeitpunkt noch etwas genauer anschauen oder Ihr werft einen Blick auf unsere HTML5 Powerwoche.

Kommentare sind geschlossen