S příchodem Promise se změnil a podstatně zjednodušil způsob, jakým je možné pracovat s asynchroními voláními v Javascriptu. Špatně škálovatelné volání callback funkcí nahradilo zpracování, které je přehledné, řetězitelné a s jednoduchým zachytáváním chyb. Od uvedení generátorů je také možné pomocí pozastavitelných funkcí zpracovávat Promise způsobem, který vypadá synchronně, ale na pozadí není (viz příklad ve článku o generátorech). Takový zápis může být mnohem čitelnější a čitelnější kód znamená snazší debugování. Až by mohlo někoho napadnout, proč něco takového není standardní součástí jazyka. A tak nám do Javascriptu přibyly slova async a await.
Async / Await
Klíčové slovo async je označením funkce, která je pozastavitelná, podobně jako generátory. V takto označené funkci pak lze použít klíčové slovo await. To automaticky vyřeší a přiřadí výsledek Promise do dané proměnné. Vezměme tento příklad, kdy na základě dat článku vypíšeme jméno jeho autora:
// Požadavek pomocí Promise function printAuthor(postId) { fetch(`api/posts/${postId}`) .then(res => res.json()) .then(post => fetch(`api/users/${post.userId}`)) .then(res => res.json()) .then(user => console.log(user.name})) .catch(error => console.log(error)) } printAuthor(42) // 'Douglas Adams'
Stejný příklad by při použití async / await vypadal takto:
// Požadavek pomocí async funkce async function printAuthorAsync(postId) { let res = await fetch(`api/posts/${postId}`) const post = await res.json() res = await fetch(`api/users/${post.userId}`) const user = await res.json() console.log(user.name) } printAuthorAsync(42) // 'Douglas Adams'
Příklad si můžete vyzkoušet zde.
Await prakticky říká "počkej, až se vyřeší tento Promise a pokračuj". To je důležitá vlastnost, protože await pracuje pouze s Promise. Pokud dostane cokoliv jiného, převede výsledek zase na Promise. Ten vždy vrací i samotná async funkce. Celý tento mechanismus je totiž postaven nad Promise a generátory. Async / await je ve skutečnosti jenom syntaktické pozlátko a využívá stávající funkce jazyka.
Výhody
Proč jej vlastně používat? Tím, že se zapisuje v podstatě synchronně, je mnohem čitelnější a nastavení breakpointů při debugování je tak mnohem jednodušší.
Protože každé zpracování Promise nemá odlišný scope, všechny hodnoty mohou být k dispozici v celém scopu funkce:
// Všechny výsledky Promise mohou být k dispozici v jednom scopu async function foo() { const a = await promise1() const b = await promise2() return {a, b} }
Taky je možné používat klasické podmínky mnohem snáze:
// Funkci lze jednodušše větvit podmínkami async function foo() { const a = await promise1() const b = await promise2() if (a > b) { return a } else { return b } }
A zachytávání výjimkek probíhá pomocí try/catch bloků:
// Chyby jsou zachytávány try/catch bloky async function foo() { try { const a = await promise1() const b = await promise2() return {a, b} } catch (error) { console.error(error) } }
Závěr
Async / await je velmi vítaným přínosem do Javascriptu. Pro asynchronní programování nabízí mnohdy čitelnější alternativu dnes rozšířeného Promise. Je podporován v NodeJS verze > 7.10 a větší částí posledních verzí moderních prohlížečů. Přesto, pokud jej hodláte použít v prohlížeči, doporučoval bych nejdříve transformaci Babelem.
Napadá vás kdy je lepší použít Promise a naopak? Máte s async / await nějaké zkušenosti? Podělte se s ostatními v komentářích.
K tomuto článku již není možné přidávat další komentáře
Komentáře
Super stranka, vysvetlenia lepsie ako v anglickych videach, ale stali mi je to malo :D