Ez a cikk az async/ await kulcsszavakkal kapcsolatos tapasztalataimról szól, amelyeket nemrég kezdtem el használni, mivel a Node 8.0.0+ teljes mértékben támogatja azt (főleg TypeScriptben, de szerintem az egész koncepciót vonatkozik az ES6-ra is).

Az Async/await funkcióval az aszinkron kód egy kicsit jobban hasonlít a szinkron kódhoz. Ebben rejlik minden ereje.

Az async/await használata egyszerű. Csak létrehozhat aszinkron funkciót, és a hívások előtt meghívhat más aszinkron függvényeket a várakozás kulcsszóval.

Így a várakozás és a hívás után minden úgy viselkedik, mintha a downloadData() által visszaadott Promise then() kezelőjében lenne.

A következő példában látható módon „klasszikus visszahívásként” is megvalósítható lett volna:

Mivel a szintaxis nagyon szép és egyszerű, nagyon könnyű megszokni await az összes hálózati és I/O hívást.

Legyen azonban óvatos, ha egymás után többször használja, mivel a await kulcsszó leállítja az utána következő kódok végrehajtását. (Pontosan olyan, mint a szinkron kódban)

A következő példában a kód nagyon tiszta és szép (ellentétben a visszahívási pokollal), de csendben is soros lett.

Ez azt jelenti, hogy a downloadFromService2() metódus nem kerül meghívásra, és a második kérés nem kerül elküldésre, mielőtt az adatok letöltődnek az 1. szolgáltatásból.

A downloadFromService3() függvényt sem hívják meg, mielőtt a downloadFromService2() befejeződik.

Képzeld el, ha az összes szolgáltatásnak ~100 ms válaszideje lenne. Akkor az egész processData() metódus több mint ~300ms-t vesz igénybe!

Nem ezt akarjuk és nem várjuk el az „eseményvezérelt, nem blokkoló I/O modelltől”. Ezenkívül egyáltalán nem kell megvárni az első kérés befejezését, mivel egyetlen más kérés sem függ annak eredményétől.

Szeretnénk, ha a kéréseket párhuzamosan küldenék el, és várnánk, hogy mindegyik egyszerre fejeződjön be. Itt rejlik az aszinkron eseményvezérelt programozás ereje.

Ennek kijavításához használhatjuk a Promise.all() metódust. Mentjük az ígéreteket az aszinkronfüggvényhívásokból változókra, egyesítjük őket egy tömbbe, és egyszerre várjuk őket.

Ez azonban csak akkor működik, ha minden kérésünk nem függő.

A való életben általában néhány aszinkronhívásunk a korábbi hívások eredményétől függ, mások pedig nem.

A következő szabályokat használhatjuk, ha a lehető legkisebb késleltetési / kérési időre szeretnénk törekedni:

  1. a lehető leghamarabb hívja meg az async függvényeket, és mentse el a visszaadott ígéreteket változó(k)ba
  2. A lehető legkésőbb várja meg a mentett ígéreteket

A valós életben való felhasználást a következő példa szemlélteti a bejegyzés adatbázisból való eltávolításával.

Először is minden lehetséges aszinkronhívást végrehajtunk. Ebben az esetben ez azt jelenti, hogy fel kell hívni az adatbázist a Hozzászólásobjektum lekéréséhez, valamint az engedélyezési szolgáltatást.

Ezután várjuk a permissionsPromise-et, mert a következő teendőnk az, hogy ellenőrizzük, hogy a felhasználó valóban eltávolíthatja-e a bejegyzéseket.

Amíg az engedély-ellenőrzés befejezésére várunk, a Bejegyzésobjektumlekérése folyamatban van a háttérben lévő adatbázisból.

Ha az engedélyellenőrzés sikeres volt, a Hozzászólás objektum lekérésével folytatjuk. Ezt úgy tesszük, hogy várunk postPromise-re, és valószínű, hogy a bejegyzés már le van töltve.
Ha ez a helyzet, a várni azonnal visszatér.

Nem egyszerűen meghívjuk a sendRemoveRequest()-t a lekért Post objektummal.

A await kulcsszó megfelelő használatával körülbelül 200 ms-ot sikerült megtakarítanunk minden egyes remove_post kérésből. Zseniális!