Hádanka pro programátory

Když už se tu tak o tom programování bavíme, tak tu mám jednu hádanku pro JavaSkriptéry

Představte si, že máte dlouhou (ve smyslu "dlouho trvající") funkci f(). Její vykonání trvá, řekněme, 5 sekund.

Ve funkci f() je na začátku zavolán asynchronní XHR (AJAX) požadavek s nadefinovanou callback funkcí callback(). Zpracování onoho požadavku trvá serveru dvě sekundy. Požadavek je asynchronn, nečeká se tedy na odpověď.

Funkce f() běží dál dvě sekundy, když přijde odpověď od serveru.

Co se stane?

Dokončí interpret běh funkce f() a pak zavolá funkci callback(), nebo přeruší běh funkce f() a vykoná callback() bezprostředně po odpovědi serveru?

Dne 14.06.2007

Twittni

Přidej do: asdf.sk StumbleUpon Toolbar Stumble It!

Komentáře

[1] (ah01 - WWW) 14.06.2007, 21:00:57 [X] [D]
Dokončí fci. f a až pak zavolá callback fci. Vychází to z toho, že JS v prohlížeči zpracovává jen jedno (právě jedno) vlákno.

[2] (Martin Hassman - Mail - WWW) 14.06.2007, 21:15:56 [X] [D]
Moc bych se nedivil, když by tohle chování doteď nebylo nijak specifikováno (pokud nesouhlasíte, prosím odkaz do specifikace). AJAXová dokumentace to zdá se neřeší, viz http://www.w3.org/TR/XMLHttpRequest/

Připravovaná specifikace HTML5 k tomu už říká: "All the executable code in a unit of related browsing contexts must execute on a single conceptual thread. The dispatch of events fired by the user agent (e.g. in response to user actions or network activity) and the execution of any scripts associated with timers must be serialised so that for each unit of related browsing contexts there is only one script being executed at a time." viz http://www.whatwg.org/specs/web-apps/current-work/multipage/section-windows.html#threads

Pro nás podstatné je ono slovíčko serialized, takže pěkně po sobě, teprv až se první dokončí.

Toť teorie, ale nedivil bych se, když by někdo našel aspoň jeden prohlížeč chovající se jinak.

[3] (karf - Mail ) 14.06.2007, 22:37:12 [X] [D]
Hmm, zajímavé. Nejsem si jist, ale když se nad tím zamyslím, tak bych si tipnul, že volání callback funkce bude fungovat na podobném principu jako event dispatching. Čili si myslím, že se zařadí do fronty událostí a zpracuje se, až na něj přijde řada.

[4] (FOUS ) 14.06.2007, 22:41:38 [X] [D]
Zrovna dneska tyhle odkazy:

http://www.javascriptkata.com/2007/06/04/ajax-and-javascript-dont-use-threads/

http://www.javascriptkata.com/2007/06/12/ajax-javascript-and-threads-the-final-truth/

budou přímo naše hádanka :)

[5] (karf - Mail ) 14.06.2007, 22:42:17 [X] [D]
A pěkné povídání je o tom zde: http://dev.opera.com/articles/view/timing-and-synchronization-in-javascript/

[6] (pixy ) 14.06.2007, 23:03:56 [X] [D]
[2] Já bych spíš viděl otázky v tom "each unit of related browsing contexts". Znamená to snad, že "pravý" AJAX (používající xmlhttprequest) se musí chovat sekvenčně, zatímco "falešný" AJAX, řekněme meziframová komunikace + data typu JSON, už může jet paralelně? Nebo ne? Co je tady ta unit? Kde je řez - box-iframe-frame-dokument-záložka-okno-instance aplikace? Ha?!

Pro mě je to dost zajímavé, protože já jsem s "pravým" ajaxem moc nedělal, pracuju nejvíc s komunikačními framy a celou dobu jsem žil v domnění, že v nich probíhá zpracování JS paralelně. Když se načtou dva framy současně, v obou se spustí JS a v obou běží současně (předpokládám!). Ovšem když frame A zavolá fci ve framu B, tak ta se slušně postaví do fronty a počká si, až na ni přijde řada... Což imho odpovídá tomuto případu - je asi jedno, odkud a proč to externí volání přiletí, že. Ale pravda taky je, že jsem timing tohoto druhu zatím nikdy nemusel řešit.

[7] (Arthur Dent [openID] - WWW) 14.06.2007, 23:18:06 [X] [D]
Kdyby to nebyl FOUS [4] profláknul, tak jsem se teď mohl vytasit s tím řešením! Tak, teď máte smůlu a za domácí úkol si můžete vyzkoušet, co se stane, když tya funkce f() je zavolána z funkce foo(). Kdy propukne callback? Po f() nebo po foo()?

No a k [6] - to je pole neorané a k výzkumu vhodné. Myslím si, že když je možné, aby to každý pochopil jinak, tak to taky každý jinak pochopí, takže rozdíly budou. No - jestli nemáš zrovna do čeho píchnout... :)

[8] (dgx - WWW) 15.06.2007, 07:52:54 [X] [D]
Za svůj programátorský život jsem psal snad ve všem, co mi přišlo pod ruku. Od C & Pascalu až po JavaScript & PHP.

Jednu věc ale nechápu. Když bych dnes psal v Javě nebo C#, dají mi vysoký plat a projeví uznání. Psát v Javě nebo C# je přitom pohodička, jazyk funguje jak má, existují fantastické IDE. Když však budu psát v PHP nebo dokonce v JavaScriptu, setkám se jen s posměšky a almužnou. Přitom v PHP se chování jazyka mění od verze k verzi, v JavaScriptu dokonce ještě záleží i na prohlížeči. A nejlepší IDE je asi Firebug :-)

Ne, programátoři v JavaScriptu mají mé uznání, autoři emailu na Centru, nebo GMailu, to jsou prostě fachmani a mistři oboru. Ne nějací svědci Javovi, co vysedávají nad kávičkou, protože už mají dávno po práci. Protože nemusí bádat nad tím, jestli se dřív spustí asynchronní AJAXová události nebo dokončí funkce f().

[9] (wake ) 15.06.2007, 07:59:19 [X] [D]
[8] no jo, jenze Java, nebo C#, jsou Enterprise Compliant jazyky, ten, kdo ma Certifikat je ten Pravy Kvalifikovany Expert na Vyvoj Enterprise-Class Software a muze tedy Naprosto OOpravnene pozadovat ostudne vysoke platy, ktery Zadnej Z Nas Nebere. Ale nebojte se, i ve webovych technologiich se blyska na lepsi casy. http://www.tibco.com/devnet/gi/default.jsp

Ja Chci Certifikaaaaaaaaaat!!!!!!!

[10] (Martin Hassman - Mail - WWW) 15.06.2007, 08:16:13 [X] [D]
[6] No jo pixy, kdyz si neprectes vsech tech stopadesataosm definic, co jsou na te odkazovane strance dokumentace, tak to pak neni divu, ze mas dalsi otazky 8-)

Ne vazne, zjednoduse receno vsechny okna, taby, (i)framy, ktere spolu maji moznost nejak v prohlizeci komunikovat (at uz pres parent opener ci child), jsou "unit of related browsing contexts". A jako takove se na ne vsechny vztahuje pravidlo jednoho threadu a serializace. Neb konec nejasnosti, konec dvojich vykladu a konec nejasnosti dvojich vykladu ([7]).

Pokud by ses v tom chtel nahodou vrtat a mel pocit, ze na
http://www.whatwg.org/specs/web-apps/current-work/multipage/section-windows.html najdes v tomto ohledu nejakou nejasnost, tak je to URCITE na report.

[11] (karf - Mail - WWW) 15.06.2007, 10:02:03 [X] [D]
[10] Dotázek: dá se working draft HTML5 od WHATWG považovat za směroplatný? Resp. popisuje to současný skutečný stav, nebo zbožné přání, jak by to mohlo fungovat, až se na tom všichni výrobci browserů shodnou a implementujou?

[12] (Martin Hassman - Mail - WWW) 15.06.2007, 10:19:51 [X] [D]
[11] Píšu, že je to teorie. Zatím teorie, za odhadem 3 roky realita. Do teď tyhle věci (vlákna, serializaci) nikdo nespecifikoval, takže si každý prohlížet v tomhle ohledu mohl dělat téměř psí kusy.

Ta specifikace není vycucaná z prstu, ale vychází z reverzního inženýrství současných prohlížečů, případně s nějakým dolaďěním, upřesněním a tak. Takže by už teď měla víceméně odpovídat realitě, ono "víceméně" je tady důležité. Pokud si dnes někdo nechce dělat reverzní inženýrství tohodle chování sám, je to asi nejlepší místo, kde začít.

[13] (dgx - WWW) 15.06.2007, 11:15:51 [X] [D]
[12] přesně tak. Whatwg.org je úžasná studnice vědomostí o vnitřnostech současných prohlížečů, nicméně každou klíčovou věc je pak nutné stejně ověřit v praxi, třeba na Velké Trojce.

[14] (dond ) 15.06.2007, 11:31:40 [X] [D]
[10] No, ono je to s tou unit ještě trochu složitější, protože platí další dvě zásady: základní JavaScriptová zásada stejného původu (kód může hrabat jenom do toho, co pochází ze "stejné" URL) a omezující vláknová podmínka maximálně dvou spojení na danou URL. Takže v reálné aplikaci, která třeba kešuje data nebo provádí intezivní dynamický crossloading, může být výsledné pořadí volání poněkud překvapivé.

Taky si nemyslím, že by chování prohlížečů bylo různé a nepopsané - teď bohužel nemám čas to najít, ale jsem si skoro jist, že tohle chování je ve specce JavaScriptu 1.4 (a nového ECMA-Scriptu asi taky) definováno poměrně přesně. Nemáte někdo čas to najít? Docela by mě to zajímalo a teď fakt nemůžu...

A konečně [8], co se týče tohot IDE - JavaScript se poměrně pohodlně dá ladit ve Visual Studiu, když člověk není prase a ví, co nedělat, vytvoří poměrně rychle spolehlivý a přenositelný kód - nedávno jsem to viděl na vlastní oči.

[15] (Null - Mail - WWW) 15.06.2007, 13:25:45 [X] [D]
[14] Asi bych si ani tímhle nebyl až tak jistej. Jsem jen obyčejnej uživatel IE7, ale mám v něm nastavených maximum parallel connections na 95 a otevírat okna/záložky v extra threadech. Jak se to bude chovat potom? :-)

[16] (dond ) 15.06.2007, 14:17:17 [X] [D]
[15] Tímhle si naprosto jistej jsem, kvůli tomu musí i naše mapové aplikace (stejně jako mapy od seznamu nebo googlu) tahat kešované dlaždice ze serverů cache1..cache256.example.com, protože pro jeden vykonávaný kód je možné otevřít v jednom čase maximálně dvě HTTP připojení z dané URL - jedno je to, kterým se tahá stránka (a kód samotný), druhé je pro XHR. Všechny další požadavky musí počkat až se jedno ze spojení uvolní.

S frejmy a okny tohle nesouvisí, resp. libovolný frejm nebo okno mají k dispozici maximálně dvě připojení.

[17] (Null - Mail - WWW) 15.06.2007, 14:50:24 [X] [D]
[16] Vidíš, a já myslel že to záleží na nastavení http serveru a http klienta. Ale jak říkám, jsem jen obyčejnej uživatel.

Každopádně není přece problém si tuhle situaci vyzkoušet. Narychlo jsem to spíchnul a hodil sem: http://undefined.cz/test/jstest.php
A světe div se, pravdu měl [1]

[18] (Martin Hassman - Mail - WWW) 15.06.2007, 15:27:25 [X] [D]
[16] Hmm, a co ve Firefoxu udělá změna řekněme takových předvoleb network.http.max-connections-per-server a max-persistent-connections-per-server? A v IE úprava registru MaxConnectionsPerServer a MaxConnectionsPer1_0Server?

[19] (pixy ) 15.06.2007, 17:57:50 [X] [D]
Udělal jsem test i pro tu meziframovou komunikaci

http://pixy.cz/temp/js_sync_test/

Je to skutečně zajímavé, tohle si budu pamatovat. Až dodnes jsem si myslel, že framy jedou nezávisle a paralelně. Nejenže je na tom vidět, že ta vzájemná volání jsou linearizovaná a stojí ve frontě a čekají, až na ně dojde řada, ale dokonce i nezávislý běh JS kódů ve dvou framech běží synchronizovaně - na koho se dostane řada, ten běží; když jeden frame vykonává funkci, druhý stojí.

Taky je zajímavé srovnání browserů - FF i Safari jedou prakticky stále stejně; IE na lokále v zásadě taky, ale ze serveru se náhodně spustí dřív JS ve framu A a jindy zase frame B. Znamená to, že frame B se dotáhne později, než je ta 100ms rezerva, kterou mu frame A dává. Ve FF ani Sf se mi to nestalo ani jednou, myslím, že tam mají poctivě oba framy přiděleny stejné prostředky a načítají se cca stejně rychle a stejně dlouho - zatímco v IE dostává vždy jeden (náhodně?) přednost. Pokud o tomhle někdo víte něco bližšího, sem s tím.

[20] (Arthur Dent [openID] - WWW) 15.06.2007, 18:15:29 [X] [D]
[19] Víš přeci že nic není tak jednoduchý jak to vypadá... Tady máš pro zajímavost Operu: http://www.maly.cz/pic/opera.jpg

[21] (Arthur Dent [openID] - WWW) 15.06.2007, 18:22:28 [X] [D]
[19] A aby nebylo všem nesystémovostem konec, tak takhle to udělá WebKit embedded prohlížeč v Adobe AIR: http://www.maly.cz/pic/webkit.jpg

[22] (Martin Hassman - Mail - WWW) 15.06.2007, 19:09:52 [X] [D]
[20-21] já myslím, že tohle už je v rámci možností prohlížeče. Pokud by na pořadí volání opravdu záleželo, musí si programátor vyřešit 'race condition', stejně jako jsou tomu zvyklí kodéři multivláknových aplikací. Představte si mutexy a semafory v JavaScriptu 8-)

Teď mě vlastně napadlo, zda ta komunikace mezi framy není takový příklad kooperativního multitaskingu, jako měli Win3.11. Ale třeba mě nějaký kodér opraví.

[23] (dond ) 18.06.2007, 09:32:48 [X] [D]
[17], [18] Aha, špatně jsem se vyjádřil. Já nemluvím o celkovém počtu současných připojení, které prohlížeč může se serverem mít. Ta se skutečně dají ovlivnit nastavením klienta a serveru. Já mluvím o tom, kolik současně otevřených připojení může mít aktuálně vykonávaný kód - a ta jsou skutečně maximálně dvě. V různých frejmech a oknech jich samozřejmě naráz může být víc - pak už ale záleží i na tom, jak moc paralelně prohlížeč pracuje s jednotlivými vlákny/podprocesy.

Snažil jsem se vysvětlit, proč jsou další volání XHR serializovaná, ale asi jsem to ještě víc zamotal.