Sliby JavaScriptu byly v JavaScriptu zjevením a poskytovaly alternativu k peklu zpětného volání JavaScriptu, ve kterém jsme se rychle ocitli. Sliby nám také umožnily zavést a lépe zvládat asynchronní úlohy. I když sliby byly zlepšením oproti peklu zpětného volání, stále vyžadují spoustu then
s které se mohou stát chaotickými. Opravdu jsem se rozhodl pro ES2017 async
a await
klíčová slova pro zjednodušení vyřizování slibů. Podívejme se na async
a await
!
Rychlé základy
async
je klíčové slovo pro deklaraci funkceawait
se používá při zpracování příslibuawait
musí být použito v rámciasync
i když Chrome nyní podporuje "top level"await
async
funkce vrátí slib, bez ohledu na to, co jereturn
hodnota je v rámci funkceasync
/await
a sliby jsou pod kapotou v podstatě stejné- Nyní je k dispozici ve většině prohlížečů a také v Node.js
Výhody async
a await
- Váš kód je jednodušší a přesnější
- Ladění je jednodušší díky menšímu počtu zpětných volání
- Konverze ze slibu
then
/catch
kód je snadný - Váš kód může být více "shora dolů", méně vnořený
Základní async
a await
Ilustrace
Vždy je nejjednodušší se učit z příkladu, takže se podívejme na velmi jednoduchý async
/ await
použití:
// Function declared as async so await can be used async function fetchContent() { // Instead of using fetch().then, use await let content = await fetch('/'); let text = await content.text(); // Inside the async function text is the request body console.log(text); // Resolve this async function with the text return text; } // Use the async function var promise = fetchContent().then(...);
Začněte deklarováním funkce jako async
; tato deklarace umožňuje await
k použití zevnitř. await
klíčové slovo je pak následováno akcí poskytující slib, což je samozřejmě fetch
API je. Asynchronní rutina (fetch
v tomto případě) běží a provádění dalšího kódu se zastaví (ačkoli neblokuje), dokud neskončí asynchronní akce. Funkce se pak vyřeší pomocí return
hodnota a slib se vrátí.
V podstatě můžete udržet svůj kód „inline“ bez nutnosti zpětných volání. Je to asynchronní o něco jednodušší!
Převod Promise Handling na await
Je velká šance, že budete chtít svůj slibový kód aktualizovat, až bude čas. Pojďme si projít příslib aktualizace na await
:
// Before: callback city! fetch('/users.json') .then(response => response.json()) .then(json => { console.log(json); }) .catch(e => { console.log('error!'); }) // After: no more callbacks! async function getJson() { try { let response = await fetch('/users.json'); let json = await response.json(); console.log(json); } catch(e) { console.log('Error!', e); } }
Přepočet ze zatížení then
s na await
se snadno provádí a váš kód snad vypadá trochu udržitelně!
async
/ await
Vzory
async
můžete deklarovat několika způsoby funkce.
Anonymní asynchronní funkce
let main = (async function() { let value = await fetch('/'); })();
Deklarace asynchronní funkce
async function main() { let value = await fetch('/'); };
Asynchronní přiřazení funkcí
let main = async function() { let value = await fetch('/'); }; // Arrow functions too! let main = async () => { let value = await fetch('/'); };
Asynchronní funkce jako argument
document.body.addEventListener('click', async function() { let value = await fetch('/'); });
Metody objektů a tříd
// Object property let obj = { async method() { let value = await fetch('/'); } }; // Class methods class MyClass { async myMethod() { let value = await fetch('/'); } }
Jak můžete vidět, přidání async
je opravdu snadné a pojme všechny pracovní postupy vytváření funkcí!
Zpracování chyb
Tradiční použití slibu vám umožňuje používat catch
zpětné volání k vyřešení odmítnutí. Když použijete await
, nejlepší je použít try
/catch
:
try { let x = await myAsyncFunction(); } catch(e) { // Error! }
Staré try
/catch
není tak okouzlující jako slibovaný catch
zpětného volání, ale je stejně efektivní.
Paralelismus
Jake Archibald ze společnosti Google uvádí v dokumentu Async functions skvělé body o tom, že není příliš sekvenční s vaším await
s. Cílem je vyhnout se čekání na skládání, pokud je to možné, a místo toho spouštět úlohy okamžitě a používat await
po uvedené úlohy jsou spuštěny:
// Will take 1000ms total! async function series() { await wait(500); await wait(500); return "done!"; } // Would take only 500ms total! async function parallel() { const wait1 = wait(500); const wait2 = wait(500); await wait1; await wait2; return "done!"; }
První blok je špatný, protože druhý wait
nastane po prvním wait
dokončí. Druhý blok je lepší metoda:spusťte obě wait
hovory a pak použijte await
; to umožňuje, aby asynchronní funkce probíhaly souběžně!
Promise.all
Ekvivalenty
Jedna z mých oblíbených funkcí Promise API je Promise.all
, který po dokončení všech načtení spustí zpětné volání. Neexistuje žádný přímý async
/ await
ekvivalent, ale tento příspěvek poskytuje dobrý ekvivalent:
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
Pamatujte si, že async
/ await
jsou v podstatě stejné jako sliby hluboko uvnitř, takže jednoduše čekáme na vyřešení agregovaného slibu!
Nyní můžete použít async
a await
ve všech hlavních prohlížečích. Tato nová klíčová slova jsou také dostupná v Node.js; starší verze Node.js mohou používat transform-async-to-generator
babel plugin pro použití async
a await
dnes. Sliby jsou stále vynikající, ale díky async
je lze lépe udržovat a await
!