Event loops
Princip a pořadí obsluhování událostí je v HTML5 specifikován pomocí Event loops. Event loops zavádí fronty úloh, do kterých se ukládají např. události uživatelského rozhraní, události parseru nebo síťového rozhraní. Specifikace popisuje, v jakém pořadí mají být dále zpracovávány.
Ačkoliv jsou webové prohlížeče s námi již řadu let, jedná se, pokud vím, o historicky první specifikaci tohoto druhu. Dosud se prohlížeče mohly chovat každý jinak, což také i víceméně dělaly (přečtěte si loňskou diskusi u Misantropa). Ve výsledku tak zmizí další rozdíl způsobující, že webová aplikace v jednom prohlížeči běžela v pořádku a ve druhém způsobila nepochopitelný problém.
Přichází vlákna
Mnohem zajímavější je ovšem zavedení vláken do skriptování webových prohlížečů. Je jim věnována zvláštní specifikace Web Workers (zkráceně WW), čítá asi 30 stran a v budoucnu se pravděpodobně stane součástí velké specifikace HTML5.
Web Workers navíc ke stávajícímu vykonávání JavaScriptu definují pracovní vlákna, která běží na pozadí (mimo interakci s uživatelským rozhraním prohlížeče) a mají sloužit ke zpracování výkonnostně nebo časově náročnějších činností. Jelikož neblokují uživatelské rozhraní, nebudou omezovány, mohou tedy bez přestání běžet desítky minut nebo i hodin (průběh stávajících skriptů totiž bývá omezen např. na desítky vteřin ve Firefoxu, což komplikuje vykonávání náročnějších úloh).
Ukažme si jednochuché použití pracovního vlákna. Všimněte si, že pracovní vlákno s vláknem uživatelského rozhraní komunikuje prostřednictvím zpráv (událost
message
) - online verze:<script>
var worker = new Worker('worker.js');
worker.onmessage = function(event){ document.getElementById('result').innerHTML = event.message;
};
</script>
Pracovní vlákno může získávat data pro svou práci pomocí událostí, database storage nebo pomocí síťové komunikace (komunikace s webovými servery pomocí AJAXu nebo nového rozhraní Web Sockets - o tom jindy). Přímý přístup k uživatelskému rozhraní nebo k zobrazované webové stránce pracovní vlákno NEMÁ.
Pracovní vlákno má navíc některé metody, např. importScripts(url1, url2...), která zajístí načtení dalších skriptů (potřebná metoda, nemůžeme totiž použít běžnou značku script, jelikož nemáme přístup k HTML dokumentu).
Kromě konstruktoru Worker existuje kontruktor SharedWorker, který založí pracovní vlákno, jenž má být sdíleno více rámy (nebo okny) aplikace.
Celá specifikace je v počátečním stádiu a výrobci prohlížečů se k ní postupně vyjadřují. Troufnu si odhadovat, že ačkoliv přináší velké změny, nakonec se do prohlížečů dostane, byť je pravděpodobné, že před tím ještě projde úpravami. S ohledem na to, že JavaScript je v prohlížečích stále rychlejší, začíná být srovnáván nejen s dalšími skriptovacími jazyky, ale třeba s céčkem, začíná být představa složitějších skriptů běžících na pozadí reálná.
Zajímavý postřeh, který se už nedostal do článku. Jelikož pracovní vlákna (Workers) v prohlížečích nesdílí žádné proměnné a nemohou spolu komunikovat přímo (ale skrze události), nestává se jejich použití tolik komplikované jako klasické vícevláknové programování na desktopech (používání zámků, mutexů apod. při jejichž nesprávném (ne)použití program kolabuje).
OdpovědětVymazatProgramování webových aplikací zůstává podobně jednoduché jako bylo dosud a stále se tomu podobá, viz používání událostí, kde pouhou změnou je, že se nejedná o události uživatel x skript, ale skript x skript.
To vypadá zajímavě. Více vláken by koneckonců mohlo také urychlit XUL aplikace jako Firefox. Zvlášť na dvou+jádrech.
OdpovědětVymazatBTW můžu poslat něco vláknu? Pokud bych poslal window, tak by mohlo přímo pracovat s UI. Ať žije abstrakce a Dependency Injection! Třeba budem mockovat i window (jakže se jmenuje ta třída?...)
Taky je zajímavé, že se do js dostane include-like řešení.
Celkově z toho dostávám pocit, že se z js stane něco použitelného (i když netypového).
v6ak
vit6ak: Offline XUL aplikace více vláken používat mohou, JavaScript ve Firefoxu umí více vláken využívat, příliš je však nepoužívá. Tuším, že celé GUI Firefoxu běží v jednom vlákně, dokonce ve stejném, ve kterém běží JavaScript všech zobrazovaných stránek.
OdpovědětVymazatPoznámkou o zasílání objektu window pracovnímu vláknu děláš z návrhářů tak trochu hlupáky. Pokud k němu totiž záměrně neumožnili přímý přístup, neumožní toto omezení ani snadno obejít. Ne, odkaz na objekt poslat nejde, pouze data. Je to architektonický záměr, viz můj komentář výše.
Není to stejné jako WorkerPool v Gears (http://code.google.com/apis/gears/api_workerpool.html)?
OdpovědětVymazatah01: Vývojáři Gearsů se na té specifikaci podílejí a ve výsledku chtějí být kompatibilní, takže to bude určitě podobné.
OdpovědětVymazat"...pracovní vlákna (Workers) v prohlížečích nesdílí žádné proměnné a nemohou spolu komunikovat přímo..." - tak pak to přece nejsou vlákna!
OdpovědětVymazatTedy, z pohledu OS to vlákna samozřejmě jsou (více execution points v jednom procesu), ale z pohledu uživatele se to chová spíš jako samostatné procesy, co komunikují pomocí nějakého mechanismu IPC (zde zprávy).
Nevím zda mechanismus workers za "vlákna" označují i tvůrci, ale mě každopádně nadpis tohoto článku dost zmátl, protože pod pojmem vlákna jsem si představil právě entity sdílející společná data. Chce to zde být s terminologií opatrný.
David: Musím se podívat na přesnou definici vláken. Nenapadlo mne, že by tam bylo tohle omezení.
OdpovědětVymazatMartin: Koukal jsem na wikipedii, http://en.wikipedia.org/wiki/Thread_(computer_science)#Threads_compared_with_processes - podle těch 4 bodů vypadají (chováním) web workers spíš jako procesy, platí pro ně všechny 4 body (i když s výhradami - u bodu 2 je otázka, co je to "considerable"; bodu 3 lze argumentovat přesným významem pojmu "address space", který já v JavaScriptu chápu jako množinu dosažitelných objektů).
OdpovědětVymazatAbych ještě vyjasnil/upřesnil svůj pohled: Myslím, že striktně technicky web workers vlákna jsou, protože AFAIK klíčová vlastnost vlákna je, že to jsou "paralelně" běžící úlohy v rámci procesu. Vlákna to budou pravděpodobně i implementací. Ale úroveň izolace, kterou web workers poskytují, není pro vlákna vůbec typická a tím může být označení za vlákna matoucí.
Aha, takže asi komunikace půjde jen skrze primitivní typy? To je trošku omezující, skoro se mi chce použít JSON nebo najít/vymyslet serializační řešení.
OdpovědětVymazatJinak pokud to nepůjde obejít takto, eval nebo jiné lepší řešení bude stačit...
Nemyslím, že bych tím z návrhářů dělal blbce. Částečně je to jen moje touha cokoli obejít. A pak s Dependency Injection to bude o něčem jiným než přímý přístup. Ale zase předávání cizích objektů by vyžádalo synchronizaci, zámky apod...
BTW jsem v6ak, vit6ak jsem použil jen proto, že v6ak na yahoo někdo obsadil. Ale na openID na blogger.com asi kašlu, z Opery mini se to chová jak chce.
Ve zprávě lze zaslat pouze string (takže ve výsledku všechny primitivní typy, ale hlavně JSON). Nebezpečný eval k parsování v budoucnu nebude potřeba, protože podpora pro JSON je ukotvena v ECMAScriptu 3.1, implementuje ji už IE8 a další prohlížeče budou rychle následovat.
OdpovědětVymazatVe výsledku by se posílal do stringu serializovaný JSON, na který příjemce zavolá nativní metodu JSON.parse. To je bezpečnější než eval, protože při tom nedojde k vykonání podstrčeného kódu.
Pro webové vývojáře je tenhle přístup vhodný, protože se nemusí učit nic moc nového, s JSON již pracovat umí. Naopak zavedení přímé interakce vláken, mutexů apod. by webové vývojáře zcela zmátlo a bylo by ostatně nekonzistetní s tím, jak se na webu programuje dnes.