Doprovodný zdrojový kód: async_await_html.zip
Většina procedurálních jazyků primárně používá blokující funkce
Například v pythonu:
jmeno = input('Kdo jsi?\n') # zde se čeká dokud uživatel nenapíše jméno # teď můžu pracovat s hodnotou proměnné jméno, mám ji načtenou print(f"Ahoj {jmeno}")
K zajištění asynchronicity (například program něco počítá, ale uživatel dál něco nastavuje v okně programu) se používají o něco (zápisem) komplikovanější postupy, které vnitřně používají vlákna (thready).
V javascriptu je to opačně. Přirozené použití vede na asynchronitu. Primárně se používají události (events); na něco jsou skvělé, na jiné věci méně.
Uvnitř funguje jednovláknový „event loop“ - ucelené kusy výpočtu se naplánují a postupně vykonají.
Často je výsledkem callback hell
Řešení (2012 ale dlouho trvalo než probublalo do prohlížečů)
let myPromise = new Promise(function(myResolve, myReject) { // "Producing Code" (May take some time) myResolve(); // when successful myReject(); // when error }); // "Consuming Code" (Must wait for a fulfilled Promise) myPromise.then( function(value) { /* code if successful */ }, function(error) { /* code if some error */ } );
Zdánlivě jen další příklad callbacku, ale `.then()` lze řetězit
new Promise(function(resolve, reject) { setTimeout(() => resolve(1), 1000); // (*) }).then(function(result) { // (**) alert(result); // 1 return result * 2; }).then(function(result) { // (***) alert(result); // 2 return result * 2; }).then(function(result) { alert(result); // 4 return result * 2; });
a existující callback funkce lze převést na promisy
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
const nactiStranku = new Promise(function(myResolve, myReject) { const xhttp = new XMLHttpRequest(); xhttp.onload = function() { myResolve(xhttp) } xhttp.onerror = function(){ myReject() } // Send a request xhttp.open("GET", "ajax_info.txt"); xhttp.send(); });
Proč vůbec stále psát then()
?
Pojďmě udělat speciální kategorii funkcí, které označíme async
await
se na daném místě „zastaví“ (ovšem s uvolněním event loopu) a počká se na splnění promise (např. dotazu na server)Příklad výsledného kódu:
const pokemoni = await nactiSeznamPokemonu() const grafika = await nactiObrazkyPokemonu(pokemoni) await pockejNaMezeru() zacniHru() /* ... */
Jediný implementační problém: await
může být použit pouze uvnitř asynchronních funkcí.
Nejsnazší řešení (ne vždy ideální ;)):
setTimeout(async function(){ // Tady už jsme v async/await prostředí (tato funkce je async) await sleep(1000) alert('Hello') })