To jasne, że kod wykonywany synchronicznie jest prostszy w pisaniu i debugowaniu, ale wystarczy sobie wyobrazić jak wyglądałyby dzisiejsze aplikacji webowe bez możliwości wykonywania kodu asynchronicznie (np ładowanie danych z zewnętrznych resources’ów). JavaScript daje nam narzędzie ułatwiające tworzenie asynchronicznych wywołań – Promise API. Promise to coś takiego co reprezentuje ewentualny rezultat asynchronicznej operacji.
Każdy promise może znajdować się w 3 stanach:
- pending – operacja w toku
- fulfilled – operacja zakończona powodzeniem
- rejected – operacja nie powiodła się
Podstawowa różnica pomiędzy wywołaniem synchronicznym i asynchronicznym:
var result; try { result = synchronousOperation(); console.log(result); } catch(error) { console.error(errror) } var result = asynchronousOperation(); result.then( result => console.log(result) ).catch( error => console.error(errror) );
Jak stworzyć promisa bez frameworka typu jQuery czy Angular ?
var promise = new Promise(resolve, reject) => { //operacja asynchroniczna if(success) resolve(“Success”); else reject(“Failure”); });
Rezultat wywołania then można zwracać do kolejnej operacji:
var result = asynchronousOperation(); result.then( result => result + ‘@’ ).then( result2 => console.log(result2) // wynik: rezultat @ );
Można również przekazywać promisa:
var result = asynchronousOperation(); result.then( result => promisifyResult(result); ).then( result2 => console.log(result2); );
Jest do bardzo przydatne szczególnie wtedy kiedy musimy wywołać wiele asynchronicznych strzałów do backendu, a wartość zwrócona z jednego requesta jest potrzebna do wywołania następnego z nich.
Promise.all
Wyobraźmy sobie jeszcze sytuacje w którym musimy wykonać wiele requestów, a aplikacja ma rozpocząć działanie dopiero wtedy gdy wszystkie są zakończone:
Promise.all([promise1, promise2, …, promiseN]).then( results => console.log(results) //wyświetli dane z wszystkich wywołań );
Promise.race
Możemy również odpalić wiele requestów, ale chcieć uzyskać rezultat tylko najszybciej zakończonego:
var promise1 = new Promise(resolve, reject) => setTimeout(‘operation1()’, 4000)); var promise2 = new Promise(resolve, reject) => setTimeout(‘operation2()’, 2000)); Promise.race([promise1, promise2]).then( winnerResult => console.log(winnerResult ); //który wykonał się szybciej ? :) );