CSS, HTML und Javascript mit {stil}

Javascript Web Worker • Arbeiten im Hintergrund

Web-Worker laufen parallel zum Haupt-Thread, aber dürfen nicht auf das DOM zugreifen

Web Worker führen Arbeiten im Hintergrund durch, ohne dabei die Benutzerschnittstelle zu blockieren.

Eine App kann ein Backup auf dem Server anlegen oder einfach nur die Änderungen am Dokument für die History oder das Protokoll starten, ohne dass der Benutzer diese Hintergrundprozesse bemerkt. Von unseren Desktop-Rechnern kennen wir solche Dienstleistungen bereits.

Javascript ist von Haus aus eine »Single Threaded« Programmiersprache und kann nicht zwei Aufgaben gleichzeitig durchführen. Es gibt kein »fork« wie z.B. in C.

Man stelle sich nur einmal vor, ein Thread würde ein Element des DOM verbergen und ein anderer Thread will das Element anzeigen …

So bleibt Javascript schön einfach und Datenstrukturen müssen nicht thread safe sein.

Asynchron vs. parallel

Javascript kann Aufgaben asynchron via setTimeout(), setInterval(), XMLHttpRequest und in Event-Handlern durchführen, aber nicht parallel zu anderen Aufgaben.

Warum das nicht reicht? Cloud Computing kommt mit großen Schritten auf uns zu. Wir werden immer öfters unsere Dokumente direkt im Web bearbeiten. Ein XMLHttpRequest() reicht dann nicht mehr …

Online-Anwendungen: Dokumente im Web bearbeiten
Dokumente auf allen Geräten bearbeiten und bereithalten

Web Worker – parallele Verarbeitung

Web Worker sind ein Kompromiss – sie laufen parallel zum Haupt-Thread, aber sie dürfen nicht auf das DOM zugreifen. Web Worker müssen für Zugriffe auf das DOM Nachrichten an den Haupt-Thread senden.

Wenn ein Web Worker Änderungen am DOM wünscht, muss der Web Worker eine Nachricht an den Haupt-Thread senden.

Das Web Worker-Script

Ein Web Worker braucht eine Javascript-Datei auf dem Server, das die Arbeiten im Hintergrund durchführt. Der Web Worker läuft also nicht im Browserfenster – ein Zugriff auf window wird demnach einen Fehler liefern. In einem Web Worker gibt es nur self. Web Worker haben keinen Zugriff auf das DOM – das kann gar nicht oft genug gesagt werden: kein getElementById(), kein window.onload … 

setTimeout(), setInterval() und XMLHttpRequest() funktionieren aber auch in Web Workern.

Web Worker Struktur

Es gibt kein Limit für die Anzahl der Web Worker, aber Web Worker stellen eine nicht unbeträchtliche Last dar und dürften nicht beliebig einsetzbar sein.

Die URL des Web Worker-Scripts wird der HTML-Seite oder App mit einem neu erzeugten Web Worker-Objekt übergeben:

var theWorker = new Worker ("web-worker.js");

Web Worker Events

Web Worker haben zwei Events: message schickt Daten vom Hintergrund-Thread zurück, das error-Event des Web Workers gibt einen evtl. Fehler zurück.

Jeder Klick auf »Web Worker starten« tickt einen Web Worker an, der Web Worker gibt eine kurze Bestätigung und beginnt dann seine Arbeit im Hintergrund. Nach getaner Arbeit (nach 5 Sekunden) meldet sich der Webworker mit einer Antwort.

Der Haupt-Thread lauscht also auf Nachrichten vom Web Worker, aber zunächst schickt der Haupt-Thread eine Nachricht an den Web Worker.

function startWW () {
   if (typeof(Worker) === "undefined") {
      document.querySelector('#msg').innerHTML = 
      "Keine Unterstützung für Web Worker in diesem Browser";
   } else {
      var theWorker = new Worker ("web-worker.js");
      theWorker.addEventListener ("message", onMessage, true);
      theWorker.addEventListener ("error", onError, true);
      
      // Daten, die wir an den Worker übergeben
      var data = "Ein Hallo von Worker ";
      theWorker.postMessage(data);
   }
}

Web Worker Event Handler

Die Funktionen onMessage und onError in diesem Beispiel sind einfach gestrickt. onMessage gibt die Antwort eines Web Workers im Textfeld aus.

Event Handler für Nachrichten und Fehlermeldungen
function onMessage (e) {
   resArea.value += "Antwort: " + e.data + " …\n";
}

function onError (e) {
   resArea.value += "Fehler: [" + e.filename + ", Zeile " + e.lineno + "] " + e.message + "\n";
}

Web Worker Skriptfehler abfangen

Die Funktion onError fängt Fehlermeldungen des Web Workers ab und gibt mit lineno Syntax-Fehler des Webworkers zurück. Fehlermeldungen des Web Workers sehen in etwa so aus:

Fehler: [web-worker.js, Zeile 12] 
ReferenceError: Can't find variable: rabbo

Auch der Web Worker in diesem Beispiel ist einfach gestrickt: Das Web Worker-Script wartet auf eine zündende Nachricht vom Haupt-Thread, bearbeitet seine Aufgabe und sendet dann eine Nachricht an den Haupt-Thread.

Web Worker Script
// verbraucht einfach nur Zeit … reine Demo
function sleep () {
   var start = new Date ().getTime();
   while (new Date().getTime() < start + delay) ;
}

// Das ist der perfekte Job … sleep
function msgHandler (e) {
   postMessage ('Erst mal eine Runde schlafen');
   sleep (5000);
   postMessage (e.data);
}

// Der Web Worker horcht auf ein message-Event
addEventListener ("message", msgHandler, true);

Wozu Web Worker?

Komplexe Berechnungen im Hintergrund werden immer wieder als Beispiel für den Einsatz von Web Workern herangezogen. Aber Web Worker eröffnen den Desktop-Anwendungen wie MS Word, Powerpoint oder Pages und Keynote den Weg in die Cloud. Web Worker können ein Backup des Dokuments im Hintergrund durchführen, 3D-Grafiken permanent rendern, während der Benutzer das 3D-Objekt im 3D-Workspace verschiebt.

Der Wordpress-Editor führt Backups still und leise durch, ohne den Benutzer zu stören – ob hier schon im Hintergrund Web Worker wirken, kann ich nicht sagen. Aber ein Backup im Hintergrund wäre eine Aufgabe für einen Web Worker.
WEBWORKER Web Worker Struktur Javascriptdocumentelementlocationnavigatorxhrattributwindowweb workerlocationnavigatorxhrself