Experimentování s webovými pracovníky

V posledních několika měsících se objevily dobré informace o webových pracovnících. Nemám chuť přidávat další úvod k tématu do blogosféry, ale rád bych se podělil o pár informací o svých zkušenostech s pracovníky webu. Následuje několik poznámek založených na mém hraní si s API.

Globální rozsah pracovníků

Zajímavá věc na dělnících je, že mají svůj vlastní globální rozsah, který je oddělený od globálního rozsahu, který všichni známe a kterého se v JavaScriptu bojíme. Pracovníci nesdílejí vlákno uživatelského rozhraní prohlížeče, které používá JavaScript na stránce ke spuštění, a proto nemají povolen přístup k modelu DOM ani k většině kusovníku. Pracovník je ve skutečnosti prostředí izolovaného prostoru, ve kterém lze JavaScript spouštět zcela odděleně od stránky. To je důvod, proč musí pracovní kód existovat v samostatném souboru, nikoli ve stejném umístění jako kód stránky. Typická tvorba vypadá takto:

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

Soubor worker.js obsahuje veškerý kód, který se má v rámci workera spustit. Tento kód se spustí v globálním rozsahu pracovníka. Globální rozsah pracovníka obsahuje omezenou sadu funkcí, včetně:

  • XMLHttpRequest konstruktor.
  • A self objekt, což je globální objekt představující pracovníka v tomto rozsahu.
  • Všechny konstruktory ECMAScript.
  • A navigator objekt obsahující pouze vlastnosti appName, appVersion, userAgent a platform.
  • A location objekt, který je stejný jako window.location kromě toho, že všechny vlastnosti jsou pouze pro čtení.
  • setTimeout() a setInterval() .
  • importScripts() metoda, která se používá k načtení externích souborů JavaScript do rozsahu pracovníka.

Stejně jako v jiných prostředích ECMAScript se globální proměnné stávají vlastnostmi na self . Většina příkladů pracovníků ukazuje opravdu špatný vzorec, který mate, co se děje:

//inside worker.js
onmessage = function(event){
    //do something in response to the event
};

Opakovaně jsem si prohlížel tento kód a snažil jsem se zjistit, co se přesně děje. Proč je k funkci přiřazena globální proměnná? Pak jsem objevil, že self je odkaz na globální rozsah pracovníka a rozhodl jsem se, že místo toho napíšu kód takto:

//inside worker.js
self.onmessage = function(event){
    //do something in response to the event
};

Tento malý dodatek dělá ukázkový kód mnohem čitelnějším, protože tento vzor je v JavaScriptu velmi běžný. Důrazně doporučuji, aby se kdokoli, kdo píše kód s webovými pracovníky, držel konvence přiřazování vlastností a volání metod přímo na self objekt, aby nedošlo k záměně. Za zmínku také stojí this ukazuje na self při přístupu v globálním rozsahu pracovníka.

Zasílání zpráv pro pracovníky

Pracovník nemůže přímo ovlivnit změnu na stránce, místo toho se spoléhá na systém zasílání zpráv, který přenáší data tam a zpět. postMessage() metoda se používá k odesílání dat do pracovníka, když je volána na Worker instance na stránce a k odeslání dat z pracovníka při volání na globální objekt pracovníka. Příklad:

//on page
var worker = new Worker("worker.js");

//receive message from the worker
worker.onmessage = function(event){
    alert(event.data);
};

//send message to the worker
worker.postMessage("Nicholas");

//in worker.js
//receive message from the page
self.onmessage = function(event){

    //send message back to the page
    this.postMessage("Hello, " + event.data);

};

API na obou stranách komunikace je naprosto stejné. Volání postMessage() způsobí message událost se spustí asynchronně na přijímači. Obsluha události musí být přiřazena pomocí starého stylu DOM 0 nastavení onmessage rovnající se funkci. event objekt má vlastnost nazvanou data který obsahuje informace od dodavatele.

Asi nejzajímavější na tomto systému zasílání zpráv je způsob přenosu dat. Můžete předat jakýkoli primitivní datový typ (řetězec, číslo, logická hodnota, null nebo undefined ) a také libovolnou instanci Object nebo Array která není součástí DOM ani kusovníku. Záludná část je v tom, že se zdá, že hodnoty jsou předávány přímo, jako například:

//on page
var worker = new Worker("worker.js");

//receive message from the worker
worker.onmessage = function(event){
    alert(event.data.name);   //"Nicholas"
};

//send object to the worker
worker.postMessage({ name: "Nicholas" });

//in worker.js
//receive message from the page
self.onmessage = function(event){

    //send message back to the page
    var name = event.data.name;   //comes through fine!
    this.postMessage(event.data);

};

Tento kód předává objekt tam a zpět mezi stránkou a webovým pracovníkem. Všimněte si, že name nemovitost je přístupná v obou lokalitách. To vytváří dojem, že předmět prochází přímo k pracovníkovi a pak zpět. Ve skutečnosti se to nemůže stát, protože pracovník je ve svém vlastním odděleném rozsahu. Ve skutečnosti se stane, že hodnota je při průchodu serializována a poté deserializována na druhé straně. Stránka a pracovník nemohou sdílet instanci objektu, pouze data reprezentovaná v objektu. Firefox to ve skutečnosti implementuje tak, že hodnotu zakóduje JSON a poté ji na druhé straně dekóduje JSON. Konečným výsledkem je vytvoření duplikátu původních dat.

Lepší zasílání zpráv

Na první pohled se systém zpráv zdá příliš jednoduchý, s postMessage() stačí přijmout jediný argument. Předávání primitivní hodnoty se zdá být špatným způsobem komunikace, protože neexistuje žádný kontext. Nyní jsem se neustále věnoval předávání předmětů, abych mohl poskytnout lepší kontext, pokud jde o důvod. Příklad:

//on page
var worker = new Worker("worker.js");

//send object to the worker
worker.postMessage({
    type: "first",
    data: "Nicholas"
});

//send object to the worker
worker.postMessage({
    type: "last",
    data: "Zakas"
});

//in worker.js
//receive message from the page
self.onmessage = function(event){

    //determine what to do
    switch(event.data.type){
        case "first":
            //do something
            break;
        case "last":
            //do something else
            break;
        //and so on...
    }
};

Tím, že vždy předáváte objekt s nějakými kontextovými daty, váš pracovník ví, co má dělat s daty, která obdržel.

Shrnutí

Pracovníci se v prohlížečích zdají být zajímavou funkcí, která se nakonec může ukázat jako užitečná. Webovým vývojářům bude chvíli trvat, než plně pochopí myšlenku JavaScriptu zaměřeného na data, který lze provést v pracovním prostředí, oproti JavaScriptu zaměřenému na DOM, který to nedokáže. V tuto chvíli však nejsem zcela přesvědčen o užitečnosti pracovníků ve většině webových aplikací. Většina příkladů, které se tam vznášejí, se zdá být cool, ale nejsou to věci, které JavaScript bude nebo by měl dělat ve webové aplikaci. Ještě jsem se nesetkal s případem, kdy bych řekl:„Ó člověče, kdyby byli široce podporováni pouze weboví pracovníci, bylo by to snadné,“ a tak jsem zvědavý, jestli ten den přijde, nebo jestli budou pracovníci zařazeni do doména proofs-of-concept bez praktických aplikací.