Pracovníci webu:chyby a ladění

Minulý víkend jsem pokračoval v experimentech s webovými pracovníky a našel jsem další zajímavé informace. Zdá se, že dřívější implementátoři, Firefox 3.5 a Safari 4, mají nějaké zvláštní rozdíly ve svých schopnostech a chování. Zjistil jsem to, když jsem se pokoušel zjistit, co by se stalo, kdyby byla uvnitř pracovníka vyvolána chyba.

Obsluha události onerror

Specifikace webových pracovníků uvádí, že error událost by se měla spustit, když dojde k chybě JavaScriptu u pracovníka. event objekt předán do onerror handler má obsahovat tři důležité vlastnosti:message, což je chybová zpráva, lineno , což je řádek v rámci pracovníka, který vyvolal chybu, a filename , což je soubor JavaScriptu, ve kterém došlo k chybě. To by mělo vám poskytne dostatek informací k řešení jakékoli chyby, která nastane. Příklad:

var worker = new Worker("worker.js");
worker.onerror = function(event){
    throw new Error(event.message + " (" + event.filename + ":" + event.lineno + ")");
};

Implementace webových pracovníků Safari nespouští error událost, kdy dojde k chybě (chyba), takže je téměř nemožné zotavit se z chyby v pracovníkovi. Implementace Firefoxu spouští error událost, ale message vlastnost na event objekt není vyplněn (chyba).

Ladění pracovníků

Safari i Firefox rozpoznávají chyby pracovníků, a proto je vydávají do příslušných konzolí. To je dobrá zpráva:můžete si být vědomi toho, že došlo k chybě. Špatná zpráva je, že nemáte žádný skutečný způsob ladění.

Firebug ani Safari’s Web Inspector nezobrazují pracovní soubory JavaScript ve svém seznamu načtených skriptů. To ve skutečnosti dává smysl, protože skript není načten do globálního rozsahu stránky, a proto se neregistruje jako používaný. I když to dává smysl, také to neuvěřitelně bolí ladění pracovního kódu.  Pamatujete si, jaké bylo ladění JavaScriptu před Firebugem? Jste tam vzadu, až na to, že je to horší.

Protože pracovní kód běží ve svém vlastním globálním rozsahu odděleném od globálního rozsahu stránky, znamená to, že nemáte přístup k console objekt. Už žádné console.log() které vám pomohou zjistit, co se děje. Možná si říkáte, že se budete muset vrátit k používání alert() , jako staré dobré časy. Špatné zprávy:alert() je metoda window a proto není k dispozici uvnitř pracovníka.

Předstírání

Bez funkčního onerror obsluhy událostí a bez přístupu k našim běžným technikám ladění je nutné přetížit jedinou událost, která skutečně funguje v Safari i Firefoxu:message událost. Ideální nastavení by vypadalo takto:

//in page
var worker = new Worker("worker.js");
worker.onmessage = function(event){
    switch (event.data.type){
        case "debug":
            console.log(event.data.message);
            break;

        //other types of data
    }
};

worker.postMessage({
    type: "start",
    value: 12345
});

//in worker.js
self.onmessage = function(event){
    if (event.data.type == "start"){
        process(event.data.value);
    }
};

function process(number){

    self.postMessage({
        type: "debug",
        message: "Starting processing..."
    });

    //code

    self.postMessage({
        type: "debug",
        message: "Processing finished"
    });
}

V tomto modelu je objekt předán zpět od pracovníka přes postMessage() . Objekt má pole type , což znamená, že zpráva je určena pro účely ladění, a message pole obsahující ladicí zprávu. Toto je pak čteno stránkou přes onmessage obslužnou rutinu události a poté je na konzolu odeslána zpráva o ladění. Všimněte si, že jsem řekl, že toto je ideální scénář vzhledem k neužitečnosti onerror . Bohužel to nelze použít, protože Safari podporuje pouze předávání řetězců přes postMessage() (Chyba). To znamená, že zprávy mohou být pouze řetězce pro implementaci napříč prohlížeči, což vede k něčemu takovému:

//in page
var worker = new Worker("worker.js");
worker.onmessage = function(event){
    var data = event.data.split(":");
    switch (data[0]){
        case "debug":
            console.log(data[1]);
            break;

        //other types of data
    }
};

worker.postMessage("start:12345");

//in worker.js
self.onmessage = function(event){
    var data = event.data.split(":");
    if (data[0] == "start"){
        process(parseInt(data[1],10));
    }
};

function process(number){

    self.postMessage("debug:Starting processing...");

    //code

    self.postMessage("debug:Processing finished");
}

Tato verze používá velmi primitivní formát řetězce s dvojtečkou oddělenou pro předávání zpráv tam a zpět (pokud Safari 4 nativně podporuje JSON, byla by to další možnost). Každý onmessage handler potřebuje analyzovat příchozí zprávu, aby určil, co má dělat, a poté podnikne příslušnou akci. Trochu otřepané, ale zvládne to.

Závěr

Weboví pracovníci jsou stále ve vývoji a mají velký potenciál, ale právě teď je spousta problémů. Rozdíly mezi jednotlivými prohlížeči jsou téměř ochromující a nedostatek možností ladění mě vede k přesvědčení, že pracovníci ještě nejsou připraveni na podnikové použití. Nikdo si nemůže dovolit trávit čas tím, že se snaží zjistit, proč jeho pracovník nepracuje (zamýšlená slovní hříčka), když se blíží termíny. Možná další iterace v každém prohlížeči přinesou lepší a rozumnější příležitosti k přijetí. Celý příběh o adopci bude podle mého názoru nakonec určen tím, do jaké míry se naše ladicí nástroje integrují s pracovníky.