02.092013

HTML5 Webworker API

Jeder Frontend-Developer, der schon mal aufwendigen Javascript Code ausführen musste, wird das Problem kennen. Sobald der Code zulange braucht, wird die Seite nicht mehr bedienbar. Das Problem dabei ist Javascript selbst. Javascript ist eine Single-Threaded-Umgebung und somit können die Scripts nicht parallel laufen. Es ist immer nur ein einziger Thread möglich.

Mithilfe von setTimeout(), setInterval(), Eventhandler sowie XMLHttpRequest versuchen wir mehr Dynamik in den Code zu bekommen, da es Asynchron abgearbeitet wird. Trotzdem wird es nicht parallel abgearbeitet, somit bleibt das Grundproblem immer noch vorhanden - Single Thread. HTML5 schafft endlich Abhilfe und liefert uns die Webworker API.

Die Webworker API bietet uns die Möglichkeit Scripts im Hintergrund ausführen zu lassen, die Webseite kann dabei wie gewohnt weiter benutzt werden. Webworker eignen sich also besonders für lange und rechenintensive Scripts aus zuführen.

Webworker Funktionszugriff

Weil der Webworker im Hintergrund läuft kann er nur auf gewisse Funktionen und Objekte zugreifen.
Erlaubt:

  • navigator Objekt
  • location Objekt (schreibgeschützt)
  • XMLHttpRequest
  • Anwendungscache
  • Import externer Scripts
  • erstellen von weiteren Webworkern

Nicht erlaubt:

  • DOM (nicht threadsicher)
  • window Objekt
  • document Objekt
  • parent Objekt

Erste Schritte

Da Webworker in einem isoliertem Thread laufen, muss das Script in eine externe Datei enthalten sein. Um den Worker das Script ausführen zulassen, müssen wir erst ein neues Worker-Objekt erstellen.

var worker = new Worker('worker.js');

Wenn das angegebene Script existiert wird es asynchron heruntergeladen. Der Worker beginnt erst nach dem herunterladen und dem ausführen des Scripts. Nachdem das getan wurde startet man den Worker mit folgender Zeile:

worker.postMessage();

Mithilfe von Ereignissen und der postMessage() Methode können Worker und Hauptseite kommunizieren. In den neuesten Versionen der Browser kann man der postMessage() ein JSON Objekt als Parameter übergeben (ältere arbeiten noch mit Zeichenketten).
Als kleines Bespiel übergeben wir jetzt unseren Worker eine Zahl und lassen die 5Mrd mal plus 1 addieren. Anhand diesem Beispiel kann man sofort erkennen, wielange der Browser dafür braucht. Die Seite aber trotzdem bedienbar bleibt.

index.php

var worker = new Worker('worker.js');
worker.addEventListener('message', function(e) {
 alert('Ergebnis ist ' + e.data);
});
worker.postMessage(0);

worker.js

self.addEventListener('message', function(e) {
 var zahl = e.data;
 for (i = 0; i < 500000000; i++) {
   zahl = zahl + 1;
 }
 self.postMessage(zahl);
});

Externe Scripts laden
Auch externe Scripts oder Bibliotheken können in den Webworker geladen werden. Dafür wird die Funktion importScripts() zur Verfügung gestellt. An diese Funktion null bis mehrere Zeichenfolgen übergeben werden.

importScript(‘script1.js’);
importScript(‘script2.js’);

oder aber so:

importScript(‘script1.js’, ‘script2.js’);

 

Webworker und Chrome

Aufgrund von Sicherheitsbeschränkungen vom Chrome können Webworker nicht lokal (file://) ausgeführt werden. Bei anderen Browsern sind solche Beschränkungen nicht vorhanden.