functiongetUsers(names) {
const userPromises = names.map(name => {
// ajax funkcija je asinkrona i vraća promisereturn ajax(`/user/${name}`).then(({ user }) => {
if (!user) {
thrownewError('User not found');
}
return user;
});
});
returnPromise.all(userPromises);
}
Stvarno cool test suite s kojim i vi možete napisati pravu Promise implementaciju.
Sinkrona funkcija: tražimo korisnika preko sync ajax poziva i ako ga nema bacamo iznimku
Verzija iste funkcije sa async callback funkcijama.
Argumenti callback funkcije (error, result) su bazirani na Node.js konvenciji:
- ako je došlo do greške, callback se poziva samo sa greškom kao prvim argumentom
- ako je pronađen rezultat, callback se poziva sa `null` kao prvim argumentom i rezultatom kao drugim argumentom
Možemo primjetiti kako async funkciji fale dvije ključne riječi koje sinkrona funkcija ima:
- return
- throw
Sync verzija funkcije getUsers():
- dohvaća korisnike sa zadanim imenima
- svi korisnici moraju postojati, ako ijedan fali bacamo iznimku greška!
Bug: ako pošaljemo dva imena za koje nema korisnika, callback će biti pozvan dva puta
Čak i ako bacimo iznimku ne možemo prekinuti izvođenje funkcije, ostali callbacks će se nastaviti izvoditi.
Pod gubitkom stacka se misli i na mogućnost da bacanje iznimke prekine izvođenje funkcije
Ne znamo koliko će se puta callback pozvati - sync funkcija vrati vrijednost najviše jednom
:rabbit: je postavio onFulfilled handler
:elephant: je postavio onRejected handler
:honeybee: je postavila onFulfilled handler koji stvara novo obećanje i poslala to obećanje svom prijatelju, koji na to obećanje može postaviti svoj onFulfilled/onRejected handler, itd...
Svi kolege mogu nastaviti sa drugim poslovima jer obećanje predstavlja rezultat asinkrone operacije
Ako :turtle: kaže da neće izvršiti, ni obećanje koje je :honeybee: dala prijatelju neće biti ispunjeno, osim ako nije postavila i error handler u kojem bi npr. naučila o Promise-ima sa interneta
Pod "neće se promijeniti" se *ne misli* na duboku nepromjenjivost (npr. ako je objekt, property-ji se mogu promijeniti).
Analogno varijabli definiranoj sa `const`.
onFulfilled će se izvršiti čak i ako je obećanje već ispunjeno u trenutku kada smo pozvali then()
Analogno vrijedi i za onRejected
Svaku async callback funkciju možemo vrlo jednostavno pretvoriti u funkciju koja vraća Promise.
Callback koji šaljemo u `new Promise` se izvršava odmah
- pozivom resolve metode pozvati će se svi zakačeni onFulfilled handleri
- pozivom reject metode pozvati će se svi zakačeni onRejected handleri
Prvi je ispunjen sa vrijednošću 5, error handler se neće pozvati
Drugi je odbijen sa greškom "Stani!", success handler se neće pozvati
Treći je ispunjen sa vrijednošću 5, success handler će pozvati samo jednom
Async kôd sada funkcionira vrlo slično sync kôdu:
- `return user.name` će vratiti novi promise koji ispunjava sa korisnikovim imenom
- ako je došlo do greške, `throw` će vratiti novi promise koji je odbačen sa greškom
- vraćenu vrijednost, ili bačenu grešku, imamo u idućem .then() pozivu: unutar success handlera, ili error handlera u slučaju greške
Sve operacije iz sinkronog svijeta su nam dostupne i u asinkronom sa Promise-ima
Sa Promises smo na određeni način dobili nazad stack: greške koje bacimo duboko u stack-u će "isplivati" na vrh, do prvog catch-a ili onRejected handlera
Promise.all() prima array promise objekata, a vraća novi promise koji:
- je ispunjen ako su *svi* promise objekti ispunjeni
- oodbačen ako je bilo koji u nizu promise-a odbačen, greška je greška prvog odbačenog promise objekta
Ako koristimo await unutar ne-async funkcije dobiti ćemo sintaksnu grešku