3. diel - React Native - Promises a asynchrónne funkcie
V minulej lekcii, Prvé aplikácie v React Native , sme si ukázali inštaláciu React Native a tvorbu aplikácií v tomto frameworku.
V dnešnom tutoriále vývoja multiplatformných mobilných aplikácií v React Native si popíšeme promises a asynchrónne funkcie a ukážeme si príklady ich využitia.
Promises v JavaScripte
Promises (budeme sa držať anglickej verzie) sú v modernom JavaScripte základom asynchrónneho programovania. Promise je objekt predstavujúci budúce dokončenie či zlyhanie a synchrónne operácie. V okamihu, keď je promisia vrátený volajúcemu, často ešte nie je operácia dokončená. Promisia ale poskytuje metódy na spracovanie prípadného úspechu, ako aj neúspechu operácie. Promisia je vždy v jednom z troch stavov:
- pending - defaultný stav, nie je ani vyriešený, ani odmietnutý,
- fulfilled - promisia je vyriešený, tzn. operácia bola úspešne dokončená,
- rejected - promisia je odmietnutý, tzn. operácia skončila neúspechom.
then()
Metóda then()
inštancie promise prijíma až dva argumenty.
Sú nimi callback funkcie pre prípad úspechu a neúspechu. Táto metóda
vracia nový promise, čo umožňuje reťaziť
ďalšie then()
metódy.
Syntax promise
Poďme sa pozrieť, ako taký promisie obvykle vyzerá:
Ukážka kódu vytvára nový
promise objekt s názvom mujPrvniPromise
. Tento objekt má ako
parametre funkcie resolve()
a reject()
:
- funkcia
resolve()
sa volá, keď operácia, ktorú promisia zastupuje, prebehne úspešne, - funkcia
reject()
sa volá v prípade, keď dôjde k nejakej chybe počas operácie.
setTimeout()
. Po uplynutí sekundy (1000
milisekúnd) je volaná funkcia resolve()
s reťazcom
"Úspěch!"
. To značí, že asynchrónna operácia bola
dokončená úspešne.
Pokiaľ by sme chceli simulovať skutočnú asynchrónnu
operáciu, namiesto setTimeout()
by sme použili napr. funkciu
fetch()
, ktorá je v JavaScripte bežne používaná pre
asynchrónne sieťové požiadavky.
Metóda then()
objektu promise definuje, čo sa má stať potom,
čo je promise úspešne vyriešený (teda keď je volaná funkcia
resolve()
). V našom prípade sa do konzoly vypíše správa
"Hurá! Úspěch!"
. No a zprava
je parameter funkcie,
ktorý obsahuje hodnotu odovzdanú metóde resolve()
- v našom
príklade je to reťazec "Úspěch!"
.
Funkcia reject()
Keď pracujeme s promises, je dôležité riadne ošetriť potenciálne
chyby. Už vieme, že funkcia reject()
slúži na označenie
promisie ako neúspešného, tzn. že operácia skončila chybou. Táto funkcia,
rovnako ako resolve()
, prijíma argument popisujúci dôvod
zlyhania. Pozrime sa na upravenú ukážku predchádzajúceho kódu:
V príklade vyššie sme
pridali jednoduchú logiku, ktorá rozhoduje, či operácia prebehla úspešne
alebo nie. Ak sa operácia nepodarí, je volaná funkcia reject()
s
chybovou správou. Na spracovanie týchto chýb v promises používame metódu
catch()
, ktorá je naviazaná po metóde then()
. V
našom príklade, ak operácia zlyhá, sa vypíše do konzoly správa
Bohužel: Něco se pokazilo!
.
Asynchrónne funkcie
Deklarácia asynchrónnej funkcie pomocou kľúčového slova
async
vytvorí inštanciu AsyncFunction
. Zakaždým,
keď je asynchrónna funkcia zavolaná, vráti nový promisie, ktorý je buď
vyriešený (pri úspechu, anglicky resolved), v takom prípade vráti hodnotu
asynchrónnej funkcie, alebo je odmietnutý (pri chybe, anglicky rejected) s
výnimkou nezachytenou v rámci asynchrónnej funkcie.
Asynchrónne funkcie môžu obsahovať ľubovoľný počet výrazov s
kľúčovým slovom await
. Kľúčové slovo await
smie byť použité iba vo vnútri asynchrónnej funkcie. Výraz s kľúčovým
slovom await
pozastaví vykonávanie kódu v asynchrónnej funkcii,
kým nie je promisia vyriešený alebo odmietnutý, čím môže dávať dojem
synchrónnej operácie. Ak je promisie vyriešený, jeho vrátená hodnota je
priradená k výrazu s kľúčovým slovom await
. Pokiaľ je
promisia odmietnutý a výraz s kľúčovým slovom await
nie je v
rámci try
/ catch
bloku, dôjde k vyhodeniu výnimky.
Asynchrónne funkcie tiež umožňujú používať try
/
catch
bloky okolo asynchrónneho kódu na zachytenie týchto
výnimiek.
Syntax asynchrónnych funkcií
Teraz sa pozrieme na jednoduchý príklad asynchrónnej funkcie:
V kóde vyššie definujeme
asynchrónnu funkciu fetchData()
. Pred definíciou funkcie je
kľúčové slovo async
, čo umožňuje v rámci tejto funkcie
používať kľúčové slovo await
.
Táto funkcia sa skladá z dvoch hlavných častí
Blok try
- na treťom riadku používame funkciu
fetch()
na získanie odpovede od špecifikovaného API. Kľúčové slovoawait
znamená, že kód bude pozastavený, kým sa nevráti odpoveď (alebo v prípade chyby výnimka), - následne používame na tejto odpovedi metódu
json()
. Je dôležité poznamenať, žejson()
je skutočne asynchrónna metóda, čo znamená, že vracia promisie. Na získanie výsledných dát vo formáte JSON z tohto promisie opäť používame kľúčové slovoawait
.
catch
- ak v akejkoľvek časti
try
bloku dôjde k chybe (napr. problém s komunikáciou s API alebo problém s parsovaním JSONu), kód vstúpi docatch
bloku, - v ňom vypisujeme chybu do konzoly pomocou metódy
console.log()
a potom ju vyhadzujeme pomocou kľúčového slovathrow
, čo umožňuje ďalšiemu kódu alebo volajúcej funkcii na túto chybu reagovať.
await
smieme použiť iba v asynchrónnej
funkcii, inak kód vyústi v SyntaxError
.
Príklady využitia asynchrónnych funkcií
Hneď ako dostaneme odpoveď pomocou fetch()
requestu, musíme
zavolať ďalšiu funkciu, aby sme získali vyžadované dáta. V tomto
príklade chceme získať dáta vo formáte JSON, preto voláme metódu
json()
. Dôležité je si uvedomiť, že aj keď
json()
spracováva odpoveď našej žiadosti, je to stále
asynchrónna funkcia. To znamená, že na získanie dát a ich
konverziu na formát JSON potrebujeme postupne zavolať dve asynchrónne
funkcie:
Toto riešenie je síce
funkčné, nie je však optimálne. Elegantnou vlastnosťou promisov je, ako sme
si už hovorili, že sama then()
metóda vracia
promisie, ktorý bude vyriešený funkciou doplnenou ako parameter. To
znamená, že tento kód môžeme (a mali by sme 🙂) prepísať do
nasledujúcej podoby:
Namiesto volania druhej
then()
metódy vnútri prvej then()
metódy sme
vrátili promisie, vrátený metódou json()
a zavolali druhú
then()
metódu na tejto vrátenej hodnote. Týmto sa vyhneme stále
zvyšujúcim sa úrovniam odsadenia pri volaní viacerých asynchrónnych
funkcií.
Teraz si poďme ukázať ešte jeden príklad asynchrónnej funkcie:
V tomto príklade
jednoduchaFunkce()
čaká na dáta zo servera. Potom sme použili
then()
metódu, aby sme vypísali výsledok operácie. Funkcia
ziskejDataZeServeru()
vracia promisie, ktorý simuluje server a je
vyriešený po uplynutí jednej sekundy. Funkcia resolve()
vracia
reťazec, ktorý je následne vypísaný do konzoly v prvej funkcii.
V budúcej lekcii, Prvá multiplatformná aplikácia , opustíme teóriu a naprogramujeme si jednoduchú aplikáciu, ktorá bude reagovať na vstup od užívateľa a zobrazí nám dialógové okno s pozdravom.