Javascript Web Worker • Arbeiten im Hintergrund

Javascript ist von Haus aus eine Single Threaded Programmiersprache und kann nicht zwei Aufgaben gleichzeitig durchführen. Während der Ausführung einer Aufgabe friert alles ein: Menüs, Scrollen, Downloads, der Aufbau und das Rendern der Seite sowie Animationen.

Javascript Web Worker

Wenn ein Script die Benutzerschnittstelle blockiert …

Web Worker führen Arbeiten im Hintergrund durch, ohne dabei die Benutzerschnittstelle zu blockieren. Da Scripte normalerweise erst ausgeführt werden, wenn die Seite vollständig geladen ist und die meisten Scripte schnell und nur in kleinen Stückchen ausgeführt werden, fallen kurze Blockaden kaum auf.

Javascript kann Aufgaben asynchron via setTimeout(), setInterval(), XMLHttpRequest oderAjax und in Event-Handlern durchführen, aber nicht parallel zu anderen Aufgaben. Eine Reihe von Javascript-Operationen wird allerdings immer synchron ausgeführt.

  • Berechnungen
  • DOM-Updates
  • Speichern und Lesen von Local Storage und IndexedDB

Dabei stottert die Benutzerschnittstelle (z.B. beim Scrollen) und langsame Geräte zeigen u.U. Seite antwortet nicht oder Script unresponsive. Es gibt kein fork wie z.B. in C. So bleibt Javascript einfach und Datenstrukturen müssen nicht thread safe sein.

Web Worker – parallele Verarbeitung

Web Worker (und auch die verwandten Service Worker) laufen nicht im Haupt-Thread. 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 Worker Änderungen am DOM wünscht, muss er eine Nachricht an den Haupt-Thread senden.

Web Worker-Demo: Primzahlen bis n

Das Beispiel für ein Web Worker-Script sucht nach allen Primzahlen bis zur eingegebenen Zahl.

⏳ Noch nichts gestartet.

const worker = new Worker("js/prime-worker.js");

const input = document.getElementById("limitInput");
const button = document.getElementById("startButton");
const status = document.getElementById("status");
const result = document.getElementById("result");

button.onclick = () => {
  const n = parseInt(input.value);
  if (isNaN(n) || n < 2) {
	status.textContent = "❌ Bitte eine gültige Zahl größer als 1 eingeben.";
	result.textContent = "";
	return;
  }

  status.textContent = `🔍 Suche Primzahlen bis ${n}...`;
  result.textContent = "";
  worker.postMessage(n);
};

worker.onmessage = (e) => {
  const { primes, limit } = e.data;
  status.textContent = `✅ ${primes.length} Primzahlen bis ${limit} gefunden.`;
  result.textContent = primes.join(", ");
};

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.

Struktur eines Web Workers
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 mit einem neu erzeugten Web Worker-Objekt übergeben:

const theWorker = new Worker ("web-worker.js");
// prime-worker.js

function isPrime(n) {
  if (n < 2) return false;
  if (n === 2) return true;
  if (n % 2 === 0) return false;
  const sqrt = Math.sqrt(n);

  for (let i = 3; i <= sqrt; i += 2) {
    if (n % i === 0) return false;
  }
  return true;
}

self.onmessage = function (e) {
  const limit = e.data;
  const primes = [2];

  for (let i = 3; i <= limit; i += 2) {
    if (isPrime(i)) {
      primes.push(i);
    }
  }
  console.log("Sende Ergebnis:", { limit, primes });
  self.postMessage({ limit, primes });
};

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.

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

WebWorker-Einsatz

Komplexe Berechnungen im Hintergrund sowie Lesen und Schreiben von localStorage und IndexedDB werden häufig als Beispiel für den Einsatz von Web Workern herangezogen. 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 ist eine typische Aufgabe für einen Web Worker.

Service Worker

Service Worker sind ein Proxy zwischen dem Browser und dem Netzwerk oder dem Cache. Sie werden im zentralen Javascript-File registriert, liegen genauso wie Web Worker in einer gesonderten Javascript-Datei und kümmern sich z.B. um Progressive Web Apps.

Sobald ein Service Worker installiert und aktiviert ist, übernehmen sie die Netzwerk-Anfragen des Dokuments und ziehen den lokalen Speicher heran, wenn der Benutzer nicht online ist.

Suchen auf mediaevent.de