Asynchronní zpracování v JavaSriptu

Oproti Javě nebo jiným běžným jazyků se JavaScript liší tím, že je jednovláknový a sekvenční, a proto využívá tzv. asynchronní zpracování, které neblokuje další tok programu.

Callback a asynchronní zpracování

Při asynchronním zpracování je obvykle potřeba reagovat na dokončení asynchronního zpracování (například dál pracovat s jeho výsledkem) a k tomu JavaScript využívá tzv. callback funkce. Princip založený na funkcionálním programování, kdy funkce může být proměnnou, a tak může být použita jako parametr nebo návratová hodnota jiné funkce.

Callback funkce se provede po dokončení asynchronního zpracování zatímco hlavní tok programy není blokován a běží dál.

Typickým příkladem asynchronního zpracování jsou události tlačítek. Callback funkci se provede jako reakce v okamžiku události (např. při stisku tlačítka). Callback funkce se tedy nevyhodnotí ihned a při tom nijak neblokuje další zpracování hlavního toku programu.

Př.:

$("#tlacitko_id").click(function() {
  //tělo této funkce se provede po stisknutí tlačítka s id = tlacitko_id
});

Asynchronní jsou v JavaScriptu typicky I/O operace (Ajax, Web Socket, databázový dotaz apod.). Využívá tzv. asynchronous non-blocking I/O model.

Vlastní asynchronní zpracování

Pokud chceme docílit asynchronní zpracování (mimo funkce poskytnuté API), lze jej v prohlížeči docílit pomoci setTimeout.

Příklad volání funkce, která se provede jako callback funkce setTimeout se zpožděním 1 s:

setTimeout( function(){ mojeSynchronniFunkce() },1000 );
setTimeout( () => mojeSynchronniFunkce(),1000 );
setTimeout( function(){ 
  //prováděný kód jako tělo anonymní funkce
},1000 );

Promise

Problém nastává, když má být výsledek asynchronního zpracování vstupem dalšího asynchronního zpracování. Callback funkce lze libovolně vnořovat, ale je to nepřehledné, mj. kromě vnořených zpracování dochází také k zanoření reakcí na chybu.

Od ECMAScript 6 byl proto zaveden Promise. Asynchronní funkce vrátí objekt typu Promise a na něj se callback funkce připojí pomocí jeho funkce then() místo toho, aby se předávala jako parametr asynchronní funkce.

Př.:

asyncFunkce(parametr).then(uspesnaCallbackFunkce, chybovaCallbackFunkce);

místo

asyncFunkce(parametr, uspesnaCallbackFunkce, chybovaCallbackFunkce);

Tato zpracování lze libovolně řetězit (místo zanořování) a naopak umožňuje mít jediné, a to společné zpracování chyb podobně jako je try-catch pro synchronní zpracování.

Př.:

asyncFce()
.then(vysledek => callbackFce(vysledek))
.then(novyVysledek => dalsiCallbackFce(novyVysledek))
.then(konecnyVysledek  => console.log(`Vypíšeme výsledek: ${konecnyVysledek}`))
.catch(fceZpracovaniChyby);