Web Workers: JavaScript s více vlákny

3. května 2011

Skripty vložené do webové stránky se skládají dohromady a vykonávají se jako její součást. Web Workers představují alternativu této staré koncepce.

Web Workers jsou API, které webovým vývojářům dovoluje oddělit náročné skripty od vlastní stránky. Na vysvětlenou: „Webovými dělníky“ jsou myšleny skripty spuštěné na pozadí webové stránky. Nemají přímý přístup k obsahu stránky, mohou si pouze vyměňovat „zprávy“ se skriptem, který je spustil.

Web Workers v akci

Skript, který má běžet na pozadí stránky, musí mít podobu samostatného javascriptového souboru. A nemůže se spustit sám, musí být spuštěn jiným skriptem přes konstruktor Worker.

<script>
var worker1 = new Worker('script1.js');
var worker2 = new Worker('script2.js');
var worker3 = new Worker('script3.js');
</script>

Skriptům běžícím na pozadí stránky nic nebrání se stránkou komunikovat. Následující skript skrze metodu postMessage() pořád předává stránce další prvočísla…

var n = 1;
search: while (true) {
  n += 1;
  for (var i = 2; i <= Math.sqrt(n); i += 1)
    if (n % i == 0) continue search;
  postMessage(n);
}

…a stránka je zpracovává, klíčová je přitom událost onmessage:

...
worker1.onmessage = function (e) {
 document.querySelector("#show").innerHTML = e.data;
};
...

Komunikace může probíhat i opačným směrem.

// odeslání dat "pracantovi"
worker2.postMessage("nějaká data");
     ↓
// přijetí dat
var nejaka_data;
onmessage = function (e) {
 nejaka_data = e.data
};

K čemu je to dobré

Z předložených ukázek zdrojového kódu je zjevné, že používání Web Workers je poznamenáno několika otravnými komplikacemi. Hlavně to, že Workers nemají přístup k obsahu stránky a že je nutné naprogramovat komunikaci mezi skripty, je důvodem k zamyšlení, v jakých případech se vyplatí Web Workers používat.

Skutečně účelné využití najdou Web Workers při provádění výpočetně náročných algoritmů. Pokud by skripty s takovými algoritmy byly integrální součástí webové stránky, uživatel by musel notný čas strávit čekáním na to, až se provedou, a on bude moci zase se stránkou, potažmo webovou aplikací normálně pracovat. Bude-li možné provádění výpočetně náročných algoritmů přenést na pozadí, bude to pro uživatele se slabšími počítači velká úleva.

Jestliže by se jednalo o extrémě náročný výpočet, mohl by se rozložit mezi více workerů. JavaScript byl sice s ohledem na svou multiplatformnost navržen na rozdíl od většiny jiných programovacích jazyků jako jendnovláknový, nicméně při určitých úpravách v internetových prohlížečích by se jednotlivé skripty teoreticky daly paralelně zpracovávat více jádry procesoru.

Web Workers mohou být prospěšní i v různých netypických případech. Například pokud si programátor není zcela jist, zda se jeho složitý algoritmums za určitých okolností nezacyklí, může jej naprogramovat jako workera. Pak by se i navzdory případnému zacyklení dalo se stránkou, potažmo aplikací ještě pracovat. Cyklus by si totiž cyklil na pozadí a neblokoval by činnost uživatele.

Díky Web Workers lze každému skriptu zvlášť stanovit, má-li být proveden podle striktního režimu (novinka z ECMAScript 5), či ne. Normálně by se skripty poskládaly dohromady a použil by se režim toho prvního.

Internet Explorer zatím Web Workers nepodporuje.

Shared Workers

Pracuje se i na konceptu, jenž by umožňoval několika stránkám sdílet společné skripty. Jak by to konkrétně mělo vypadat? Jednalo by se vlastně o mírně složitější Web Workers. Ukážeme si to na následujícím příkladu.

Zde je kód webové stránky, do níž je prostřednictvím iframe vložena další stránka:

<!DOCTYPE html>
<title>Shared workers: main page</title>
<pre id="log">Log:</pre>
<script>
  var worker = new SharedWorker('test.js');
  var log = document.getElementById('log');
  worker.port.addEventListener('message', function(e) {
    log.textContent += '\n' + e.data;
  }, false);
  worker.port.start();
  worker.port.postMessage('ping');
</script>
<iframe src="inner.html"></iframe>

A zde máme kód vnořené stránky:

<!DOCTYPE html>
<title>Shared workers: inner frame</title>
<pre id="log">Inner log:</pre>
<script>
  var worker = new SharedWorker('test.js');
  var log = document.getElementById('log');
  worker.port.onmessage = function(e) {
   log.textContent += '\n' + e.data;
  }
</script>

Povšiměme si jedné důležité věci: Komunikace s workerem tady probíhá přes objekt port, který je přidružený každé instanci SharedWorker. Už příkaz worker.postMessage('ping'); by tedy způsobil chybu.

To nejlepší na konec. Kód sdíleného skriptu:

var count = 0;
onconnect = function(e) {
  count += 1;
  var port = e.ports[0];
  port.postMessage('Hello World! You are connection #' + count);
  port.onmessage = function(e) {
    port.postMessage('pong');
  }
}

Perspektiva

Je obtížné nyní odhadovat, jak intenzivně se budou Web Workers využívat. Drtivá většina věcí se dá udělat jednodušeji bez nich. Webové aplikace však mají tendenci být stále větší, složitější a multifunkčnější, a právě do takových obludných aplikací by Web Workers výborně zapadli.

Mohlo by vás také zajímat

Nejnovější

2 komentářů

  1. goddard

    Kvě 12, 2011 v 10:12

    Prosim vas, to logo je logo Javy. Java != JavaScript.

    Odpovědět
  2. Mooph

    Čvc 10, 2011 v 16:14

    Existují i jiné způsoby vícevláknového programování v javascriptu. Jako příklad bych uvedl svou hru na http://strateg.yga.me.

    Odpovědět

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *