Přejít k navigační liště

Zdroják » JavaScript » Stroj času k ladění asynchroního JavaScriptu v Chrome DevTools

Stroj času k ladění asynchroního JavaScriptu v Chrome DevTools

Články JavaScript

Vývojářské nástroje v Google Chrome přináší zajímavou novinku. Jedná se o stroj času, pomocí kterého můžete snadno ladit ajaxová volání, resp. procházet různými stavy vaší aplikace v čase pomocí zásobníku asynchronních volání.

Tento článek je překladem textu Debugging Asynchronous JavaScript with Chrome DevTools od Pearl Chen a je zveřejněn pod licencí CC BY 3.0.

Úvod

Asynchronní zpracování pomocí callback funkcí je mocnou stránkou JavaScriptu, ale současně se dost špatně ladí.

Naštěstí Chrome Canary DevTools přináší řešení, můžete v něm vidět celý zásobník javascriptových asynchronních volání!

A quick teaser overview of async call stacks
Na začátek takový rychlý náhled, jak to celé funguje.

 

Jakmile povolíte zásobník asynchronních volání v DevTools, můžete se nořit do různých stavů vaší webové aplikace v čase. Můžete procházet celý zásobník handlerů událostí, volání setInterval, setTimeout, XMLHttpRequest, promises, requestAnimationFrame, MutationObservers a další.

Jak budete zásobníkem volání procházet, můžete současně analyzovat hodnoty jakékoliv proměnné v daném bodě spuštění vaší aplikace. Funguje to podobně jako stroj času.

Pojďme se podívat na několik scénářů použití.

Jak povolit asynchronní ladění v Chrome Canary

Použijte Chrome Canary (build 35 nebo vyšší). Zobrazte si panel Sources v DevTools.

Hned vedle panelu Call Stack napravo najdete checkbox „Async“. Ten asynchronní ladění zapíná a vypíná.

Toggle the async feature on or off

Zachytávání událostí časovače a XHR odpovědí

Nejspíš jste něco podobného v Gmailu už viděli:

Gmail retrying to send an email

Pokud nastane problém při odesílání požadavku (ať už je problém na serveru nebo v síťové konektivitě klienta), Gmail se po krátké odmlce automaticky pokusí zprávu poslat znovu.

Abychom si to mohli snadno vyzkoušet, vytvořila jsem mockup Gmailu. Funguje dle schématu:

Flow chart of mock Gmail example
Metody modře zvýrazněné fungují asynchronně.

 

Pokud se podíváte na obyčejný zásobník volání, tak breakpoint na postOnFail() vám nic moc nenapoví, odkud byla funkce vyvolána. Zkusme zapnout asynchronní zásobník a hned je jasno:

Předtím:

Breakpoint set in mock Gmail example without async call stacks
Klasický zásobník, vidíme, že postOnFail() je ajaxový callback, ale nic víc.

Potom:

Breakpoint set in mock Gmail example with async call stacks
Asynchronní zásobník volání, vidíme, že XHR vyvolal submitHandler(), který byl vyvolán obsluhou události click ze scripts.js. Pěkné!

 

V celém zásobníku pak uvidíme, že požadavek pochází buď z submitHandler() jako na obrázku výše anebo z  retrySubmit() jako na obrázku níže:

Another breakpoint set in mock Gmail example with async call stacks

Ze zásobníku také poznáme, zda byl požadavek vyvolán obsluhou události, např. kliknutím nebo metodou setTimeout() nebo některou z dalších asynchronních metod.

Sledujte výrazy asynchronně

Při procházení asynchronním zásobníkem můžete sledovat vybrané výrazy (watch expression), které budou zobrazovat hodnotu odpovídající patřičnému stavu aplikace v čase!

An example of using watch expressions with aysnc call stacks

Změňte minulost aneb jak vykonat kód v minulých rozsazích působnosti (scopes)

Minulost můžete nejen zkoumat, ale také v ní spouštět váš kód pomocí javascriptové console.

Představte si, že jste Doktorem Who a potřebujete porovnat čas před vstupem do TARDIS a „nyní“. Žádný problém.

An example of using the JavaScript console with aysnc call stacks
Použití javascriptové konzole ve spojení s asynchronním zásobníkem. Demo použité v obrázku najdete zde.

 

Ušetří vám to čas. Můžete zůstat a pracovat v DevTools, místo abyste přepínali do vašich zdrojáků, upravovali je, znovu načítali atd.

Brzy uvidíte: použití se zřetězenými promises

A co teprve, pokud používáte promises. Převezmu finální příklad z tutoriálu Jake Archibalda k javascriptovým promises.

Flow diagram s javascriptovými promises.

 

Předtím:

Breakpoint set in promises example without async call stacks
Klasický zásobník, všimněte i, že v panelu Call Stack toho opravdu moc není.

 

Potom:

Breakpoint set in promises example with async call stacks
A nyní? Skvělé! Náš zásobník je plný.

 

Podpora pro promises se objeví brzy (doufejme, že v Chrome 36). Pokud si ji chcete vyzkoušet už dnes, můžete si ji v Chrome 33 nebo Chrome 34 zapnout na stránce chrome://flags/#enable-devtools-experiments povolením Developer Tools experimentů. Po restartu prohlížeče najdete v nastavení DevTools volbu enable support for async stack traces.

Projděme se animací

Můžeme jít ještě dál. Paul Lewis napsal článek Leaner, Meaner, Faster Animations with requestAnimationFrame. Otevřeme si jeho requestAnimationFrame demo a nastavíme breakpoint na začátek metody update() method (okolo řádku 874) v post.html.

Předtím:

Breakpoint set in requestAnimationFrame example without async call stacks
Panel Call Stack toho moc neobsahuje.

 

Potom:

Breakpoint set in requestAnimationFrame example with async call stacks
A nyní?

 

Sledování změn DOMu pomocí MutationObserverů

MutationObserver nám umožňuje sledovat změny v DOMu. V tomto jednoduchém příkladu je po kliknutí na tlačítko přidán na konec dokumentu <div class="rows"></div>.

 

Přidáme breakpoint do metody nodeAdded() (řádka 31) v demo.html a podíváme se na výsledek.

Předtím:

Breakpoint set in mutationObserver example without async call stacks
Obyčejný zásobník

 

Potom:

Breakpoint set in mutationObserver example with async call stacks
Asynchronní zásobník

 

Tipy k ladění asynchronního JavaScriptu

Pojmenujte vaše funkce

Pokud používáte ve vašich callbacích anonymní funkce, můžete je místo toho chtít pojmenovat, což procházení asynchonním zásobníkem dost zjednoduší.

Místo anonymní funkce:

window.addEventListener('load', function(){
  // do something
});

Zkuste:

window.addEventListener('load', function windowLoaded(){
  // do something
});

A výsledek?

S anonymní funkcí:

An anonymous function

S pojmenovanou funkcí:

A named function

Shrnutí

Přehled asynchronních callbacků, které můžete sledovat v asynchronním zásobníku:

  • Timers: metody setTimeout() a setInterval()
  • XHRs: zavolání xhr.send()
  • Animation frames: volání requestAnimationFrame.
  • Event listeners: vysledování až k addEventListener().
  • MutationObservers: sledování, jaká událost je vyvolala.

A brzy přibude podpora pro tato experimentální javascriptová API:

  • Promises
  • Object.observe

Komentáře

Subscribe
Upozornit na
guest
13 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
steinbauer

Díky za článek – pěkný.

Jen dvě drobné chybičky:

  • „vytvořila jsem“ – Martin postupuje změnu pohlaví?
  • poslední dvě fota (před a po pojmenovaní funkce) jsou stejné
tarmaq
  1. Autorka clanku je skutecne zena
  2. Posledni dve fota sice vypadaji stejne, ale v druhem je „windowLoaded“ namisto „(anonymous function)“
steinbauer

A jo, díky.
K bodu dva: koukal jsem na to dolní anonymous, ne na horní. Díky.

Jirka Kosek

Ono by stačilo, aby se články, co jsou překlad, netvářili, že jsou od předkladatele, ale původního autora, a byl by klid. :-)

Jirka Kosek

Já zas nechápu, co v tom má být za problém. Spoustu časopisů (I tištěných) uvádí jméno originálního autora a pod článkem jen přidá řádku „přeloženo z…“

vaclav.sir

Proč překopávat autorství? Stačí k článku přidat parametry se jménem, popisem a fotkou původního autora a pokud jsou vyplněné, tak se vypíší někde tam, kde se vypisuje redakční autor. Třeba nad ním, nebo vedle. To zvládne i ten váš WordPress. Teď když odroluju na konec článku, dozvím se, kdo je Martin Hassman a ani by mě nenapadlo, že autorem článku může být někdo jiný.

fish

zkousel jsem to na jednom dizkuznim foru a pri zapnutem ASync neni prohlizec schopen nacist stranku, stale se objevuje znama screen s chybou. takze za me – nelze se na to spolehnout, tudiz vhodne na experimenty

skiper.skiprovic

JS callbacky patri vystrelit smerem do slunce, od doby co Kris Kowal napsal „q“ se jim s uspechem vyhybam a Zeme je znova planeta na ktere se da zit.
.done();

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.