Zum Inhalt springen
Der Guide für ein smartes Leben.
Programmierung

JavaScript parallel ausführen mit der Web Workers API

Das "dynamische Duo", bestehend aus W3C und WHATWG, hat der Weiterentwicklung von Web-Standards endlich neues Leben eingehaucht: Zuerst kam der HTML5-Standard und dann die Web Workers API.

Autoren: Anna Kobylinska und Filipe Pereira Martins • 19.5.2011 • ca. 3:45 Min

internet, webdesign, javascript, web workers api, html5, w3c, whatwg
internet, webdesign, javascript, web workers api, html5, w3c, whatwg
© Internet Magazin
Inhalt
  1. JavaScript parallel ausführen mit der Web Workers API
  2. Web Worker terminieren
  3. Threads für JavaScript

Hinsichtlich der Fähigkeiten und Performance von JavaScript haben sich in der letzten Zeit große Fortschritte ergeben. Dennoch erschwert eine Vielzahl von Flaschenhälsen die Umsetzung von Web-Applikationen in reinem JavaScript. Vor allem serverseitige Web-Anwendungen lassen sich nur sehr mühsam ...

Hinsichtlich der Fähigkeiten und Performance von JavaScript haben sich in der letzten Zeit große Fortschritte ergeben. Dennoch erschwert eine Vielzahl von Flaschenhälsen die Umsetzung von Web-Applikationen in reinem JavaScript. Vor allem serverseitige Web-Anwendungen lassen sich nur sehr mühsam auf das clientseitige JavaScript umstellen. Die Gründe hierfür sind vielfältig; sie reichen von Browser- Kompatibilitätsproblemen bis hin zu Leistungsengpässen.

Flüchtige Herausforderung

Bei JavaScript handelt es sich um eine sogenannte single-threaded Umgebung: Mehrere JavaScript-Skripte können nicht gleichzeitig in separaten Threads ablaufen. Eine Webseite, bei der es gilt, UI-Ereignisse auszuwerten, große Mengen an Daten via verschiedener APIs abzufragen und auszuwerten und schließlich das DOM zu verändern, stellt durchaus kein außergewöhnliches Szenario für den Einsatz von JavaScript dar.Dennoch ist JavaScript nicht wirklich dafür ausgelegt, diese Aufgaben in Echtzeit zu handhaben. Die wichtigste Einschränkung bestand bisher darin, dass die Ausführung von JavaScript-Skripten in der Browser-Runtime in einem einzelnen Thread erfolgen musste.Man könnte jetzt einwenden, dass es Entwicklern inzwischen gelungen ist, mittels bestimmter Programmiertechniken in gewissen Grenzen Gleichzeitigkeit zu erzielen. Mit den Methoden setTimeout(), setInterval(), XMLHttpRequest und Event-Handlern lässt sich der Eindruck von Gleichzeitigkeit vermitteln. Zugegebenermaßen laufen alle diese Funktionen asynchron, aber nicht-blockierende Skripte bedeuten noch lange nicht wirkliche Gleichzeitigkeit. Dank der Web Workers API in HTML 5 können JavaScript-Entwickler auf diese improvisierten Lösungen endlich verzichten.Die Web Workers-Spezifikation legt eine API zum Einbinden von Hintergrundskripten in eine Webseite fest. Mittels Web Workers ist es möglich, Skripte zum Ausführen rechenintensiver Tasks clientseitig laufen zu lassen, ohne jedoch die Benutzeroberfläche der Ursprungsseite oder andere Skripte zu blockieren und Benutzerinteraktionen zu hindern. Auf diese Weise werden JavaScripte, die nicht mehr reagieren, endlich der Vergangenheit angehören.

Web Workers ins Leben rufen

internet, webdesign, javascript, web workers api, html5, w3c, whatwg
Really Cloudy ist ein quelloffenes Projekt für verteiltes Computing mittels der Web Workers API (www.theplanis.com).
© Internet Magazin

Ein Web Worker läuft in einem isolierten Thread ab. Aus diesem Grunde muss der auszuführende Quelltext in einer separaten Datei vorliegen.Die WHATWG-Spezifikation sieht zwei Arten von Web Workers vor: dedizierte Workers und gemeinsam genutzte Workers. Browserunterstützung für die Letzteren beschränkt sich derzeit auf aktuelle Versionen von Google Chrome, Apple Safari und Opera.Um einen dedizierten Web Worker zu erzeugen, übergeben Sie den Namen der JavaScript-Datei, die den Code des Workers beinhaltet, an eine neue Instanz des Objektes Worker:

var worker = new Worker
("dedizierterWorker.js");

Um einen gemeinsam genutzten Web Worker ins Leben zu rufen, übergeben Sie den Dateinamen der JavaScript-Datei des Workers an eine neue Instanz des Objektes SharedWorker:

var worker = new SharedWorker
("sharedWorker.js");

Falls die angegebene Datei existiert, erzeugt der Browser einen neuen Thread für diesen Worker und lädt das Skript asynchron herunter. Der Worker wird mit seiner Arbeit aber erst beginnen, nachdem die Datei komplett heruntergeladen und ausgeführt werden konnte. Sollte der Zugriff auf den Zielpfad mit einer 404-Fehlermeldung scheitern, wird der Start des Workers leise fehlschlagen.Nach dem Erstellen des Workers lässt sich dieser mittels der postMessage()-Methode zum Beispiel wie folgt ansprechen:

worker.postMessage(): // Aufruf des
Workers

Kommunikation mit einem dedizierten Worker

Die Kommunikation zwischen einem dedizierten Worker und der Ursprungswebseite basiert auf einem Event-Model und der postMessage()-Methode. Je nach Browser- Version kann diese Methode eine Textzeichenkette oder (in neueren Webbrowsern) ein JSON-Objekt als (ihr einziges) Argument entgegennehmen.Im einfachsten Fall könnte ein dedizierter Worker eine Textzeichenkette entgegennehmen und an die Ursprungsseite zurückgeben. Im Beispiel empfängt der Worker in TextausgabeWorker.js die Nachricht "Internet Magazin" von dem Skript in der Ursprungsseite:

var worker = new Worker
("TextausgabeWorker.js");
worker.addEventListener("message",
function(e) { console.log("Mitteilung
des Workers: ,, e.data);
}, false);
worker.postMessage("Internet
Magazin"); // Die Daten werden an
den Worker verschickt

Die JavaScript-Datei des Workers - TextausgabeWorker.js - beinhaltet den folgenden Code:

self.
addEventListener
("message",
function(e) {
self.postMessage(e.data);
}, false);

Wird die Methode postMessage() von der Ursprungswebseite aufgerufen, erzeugt der Worker für die eingehende Nachricht einen onmessage-Handler. Die Nachrichtendaten (im Beispiel also die Textzeichenkette "Internet Magazin") sind in e.data zugänglich. Mithilfe der postMessage()-Methode werden Daten auch wieder zurück zum Thread der Ursprungsseite weitergereicht.Zum Übermitteln von Nachrichten zwischen der Webseite und ihren dedizierten Workers werden diese Daten nicht gemeinsam genutzt, sondern kopiert. Die meisten Browser codieren und decodieren die betreffenden Daten als JSON-Objekte. Die Übergabe von Mitteilungen unter Verwendung eines JSON-Objektes veranschaulicht das folgende Beispiel.Die Ursprungsseite beinhaltet den folgenden Quelltext:

<button onclick="InternetMagazin()">Willkommen zum Internet Magazin</button><button onclick="unknownCmd()">
Unbekannter Befehl</button><button onclick="stop()">Halte den
Web Worker an</button><output id="result"></output><script>
function InternetMagazin() {
worker.postMessage({"cmd": "start",
"msg": "Hallo"});
}
function stop() {
// der Aufruf von worker.terminate()
von diesem Skript heraus würden den
Worker endgültig beenden
worker.postMessage({"cmd": "stop",
"msg": "Auf Wiedersehen"});
}
function unknownCmd() {
worker.postMessage({"cmd": "Befehl",
"msg": "?"});
}
var worker = new Worker
("WorkerRoutine2.js");
worker.addEventListener("message",
function(e) {
document.getElementById("result").
textContent = e.data;
}, false);</script>