
Akkor beszélünk promise-ról, amikor egy olyan műveletet hajtunk végre, ami nem azonnal ér véget. Nem azonnal produkál eredményt. Bővebben…
Példa a való életből
Ha üres üzemanyag tartállyal áthajtok egy benzinkúton, akkor nem lesz tőle tele a tankom. Ehelyett szépen oda kell állnom valamelyik töltőállomás mellé, adott esetben ki kell várnom a soromat is. De, ha nincs előttem senki sem, akkor is időbe telik, míg megtankolom a kocsit.
Tehát nem azonnal lesz tele a tank. Az eredmény pedig részemről lehet siker, ha véletlenül találok 95 prémium benzint és azzal tudom megitatni a „lovat”. Vagy lehet akár kudarc is (error), ha azon mérgelődöm, hogy sima E10 van a kúton, vagy esetleg ki van írva, hogy nincs benya :). Vagy, ami még rosszabb, hogy otthon felejtem a forgalmit, és akkor ugrik a hatósági árkedvezmény.
Példa a programozás világából
Az szintén egy promise-t eredményez, amikor mondjuk a Firebase authentikációját használom arra, hogy egy felhasználót beléptessek. Mivel az interneten zajlik az egész, időbe telik míg elmegy a kérés a Firebase felé, illetve onnan megjön a válasz.
Tehát már értjük, hogy mi az a promise. A következőben azt szeretném megmutatni, hogyan tudunk egy promise-t átírni az ugyanazt csináló, de szerintem áttekinthetőbb async/await formára.
A konkrét feladat
Az előbb említett példán mennék tovább. Egy felhasználót akarunk beléptetni email címmel és jelszóval. Ezért meghívjuk a Firebase signInWithEmailAndPassword függvényét. Az most mindegy, hogy emögött milyen logika áll. A függvénynek át kell adni egy auth paramétert, ami most szintén mindegy, hogy mit csinál. Továbbá egy email címet és jelszót. (Ezeket adja meg a felhasználó a felületről.)
A signInWithEmailAndPassword egy promise-t ad vissza. Na, de nézzük a kódot először a promise feldolgozásával, ahogyan async/await előtt csináltuk (és persze csinálhatjuk most is):
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// sikeres belépés
const user = userCredential.user;
console.log(user);
})
.catch((error) => {
// valami hiba
const errorCode = error.code;
const errorMessage = error.message;
console.log(error.message);
});
A promise-nek meghívjuk a .then() metódusát, aminek a paramétere egy nyílfüggvény. Ez a nyílfüggvény megkap egy userCredential nevű paramétert, amiben a promise visszaadja nekünk a felhasználó azonosításával kapcsolatos objektumot. Ebből ki tudjuk bányászni a user objektumot, ami a felhasználót tartalmazza, sok-sok tulajdonsággal. Tehát a .then()-el oldottuk fel a promise-t.
Én az egyszerűség kedvéért, csak annyit csináltam, hogy sikeres lekérés esetén kiírattam a konzolba a user objektumot.
A hibakezelés részét a promise .catch() metódusával intézzük. Ez szintén egy nyílfüggvény paramétert kap. Ennek a nyílfüggvénynek egy error objektum az inputja. A törzsében pedig ezt az errort dobtam szét hibakódra és hibaüzenetre és ki is írtam. (Ezt úgy lehet tesztelni, hogy hibás email címet és/vagy jelszót adunk meg a felületről.)
Hogyan néz ki mindez async/await formában?
async function signIn() {
try {
const userCredential = await signInWithEmailAndPassword(auth, email, password);
const user = userCredential.user;
console.log(user);
} catch (error) {
const errorCode = error.code;
const errorMessage = error.message;
console.log(error.message);
}
}
Először is az egészet beletettem egy függvénybe (signIn). Ez azért is fontos, mert az await csak egy olyan függvényen belül működik, aminek a definícióját az async kulcsszó előzi meg.
Létrehoztam tehát a signIn nevű függvényt, aminek a hasában a promise-t eltároltam egy userCredential nevű változóban. Ha ezt kiíratnám a konzolba, akkor magát a promise objektumot kapnám meg. Ettől még nem lennénk túl boldogak.
Ezért a nagyon-nagyon fontos dolog, hogy a signInWithEmailAndPassword függvény hívás elé tettem be az await kulcsszót. Ez az a függvény vagy metódus, ami aszinkron módon működik.
Egy függvény általában undefined értékkel tér vissza, ha nincsen return utasítás. De azzal, hogy a signIn függvény definíciója elé betettem az async-et, a belsejében pedig az await-et, a függvény már egy promise-t ad vissza.
A csodát pedig az await csinálja. Ugyanis ez fel is oldja (vagy, ha úgy tetszik feldolgozza) a promise-t és egyből az értéket kapjuk vissza, akárcsak a .then()-el.
Persze a hibát itt is célszerű kezelni. Ezt egy try-catch szerkezettel oldottam meg.
Az async/await átalakítás haszna
Az async/await átalakítás igazi előnye abban mutatkozik meg, hogy ha egy promise-on belül egy másik promise-t kapunk vissza, akkor azt szintén egy újabb .then()-el kellene feloldani. Tehát a végén kapnánk egy .then() után láncolt újabb .then()-t. Nem szép látvány az ilyen :).
Az await-tel viszont azonnal az eredményt kapjuk vissza, még ha az is egy promise. De sokkal áttekinthetőbb kódot eredményez.