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.
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.
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 );
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);