# Pangaäpi loomine, 3. osa: Andmete hankimise ja kasutamise meetodid ## Eelloengu viktoriin [Eelloengu viktoriin](https://ff-quizzes.netlify.app/web/quiz/45) ### Sissejuhatus Iga veebirakenduse keskmes on *andmed*. Andmed võivad olla mitmesugusel kujul, kuid nende peamine eesmärk on alati kuvada kasutajale teavet. Kuna veebirakendused muutuvad üha interaktiivsemaks ja keerukamaks, on see, kuidas kasutaja teabele juurde pääseb ja sellega suhtleb, nüüd veebiarenduse oluline osa. Selles õppetükis vaatame, kuidas hankida andmeid serverist asünkroonselt ja kasutada neid andmeid teabe kuvamiseks veebilehel ilma HTML-i uuesti laadimata. ### Eeltingimused Selle õppetüki jaoks peate olema loonud veebirakenduse [sisselogimise ja registreerimise vormi](../2-forms/README.md) osa. Samuti peate installima [Node.js](https://nodejs.org) ja [käivitama serveri API](../api/README.md) lokaalselt, et saada kontoteavet. Saate testida, kas server töötab korralikult, käivitades terminalis järgmise käsu: ```sh curl http://localhost:5000/api # -> should return "Bank API v1.0.0" as a result ``` --- ## AJAX ja andmete hankimine Traditsioonilised veebilehed uuendavad kuvatavat sisu, kui kasutaja valib lingi või esitab vormi kaudu andmeid, laadides HTML-lehe täielikult uuesti. Iga kord, kui on vaja laadida uusi andmeid, tagastab veebiserver täiesti uue HTML-lehe, mida brauser peab töötlema, katkestades praeguse kasutaja tegevuse ja piirates interaktsioone laadimise ajal. Seda töövoogu nimetatakse ka *mitmelehe rakenduseks* ehk *MPA*-ks.  Kui veebirakendused hakkasid muutuma keerukamaks ja interaktiivsemaks, tekkis uus tehnika nimega [AJAX (Asynchronous JavaScript and XML)](https://en.wikipedia.org/wiki/Ajax_(programming)). See tehnika võimaldab veebirakendustel saata ja hankida andmeid serverist asünkroonselt JavaScripti abil, ilma HTML-lehte uuesti laadimata, mis tagab kiiremad uuendused ja sujuvamad kasutajainteraktsioonid. Kui serverist saadakse uusi andmeid, saab praegust HTML-lehte JavaScripti abil uuendada, kasutades [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model) API-d. Aja jooksul on see lähenemine arenenud ja seda nimetatakse nüüd [*ühelehe rakenduseks* ehk *SPA*-ks](https://en.wikipedia.org/wiki/Single-page_application).  Kui AJAX esmakordselt kasutusele võeti, oli ainus API, mis võimaldas andmeid asünkroonselt hankida, [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Kuid tänapäeva brauserid rakendavad nüüd ka mugavamat ja võimsamat [`Fetch` API-d](https://developer.mozilla.org/docs/Web/API/Fetch_API), mis kasutab lubadusi (promises) ja sobib paremini JSON-andmete manipuleerimiseks. > Kuigi kõik kaasaegsed brauserid toetavad `Fetch API-d`, on alati hea mõte kontrollida [ühilduvustabelit caniuse.com-is](https://caniuse.com/fetch), kui soovite, et teie veebirakendus töötaks vanemates brauserites. ### Ülesanne [Eelmises õppetükis](../2-forms/README.md) rakendasime registreerimisvormi konto loomiseks. Nüüd lisame koodi, et saaks olemasoleva kontoga sisse logida ja selle andmeid hankida. Avage `app.js` fail ja lisage uus `login` funktsioon: ```js async function login() { const loginForm = document.getElementById('loginForm') const user = loginForm.user.value; } ``` Siin alustame vormielemendi hankimisega `getElementById()` abil ja seejärel saame kasutajanime sisendist `loginForm.user.value`. Iga vormikontrolli saab HTML-is `name` atribuudi abil määratud nime järgi vormi omadusena kasutada. Sarnaselt sellele, mida tegime registreerimise puhul, loome teise funktsiooni serveripäringu tegemiseks, kuid seekord kontoandmete hankimiseks: ```js async function getAccount(user) { try { const response = await fetch('//localhost:5000/api/accounts/' + encodeURIComponent(user)); return await response.json(); } catch (error) { return { error: error.message || 'Unknown error' }; } } ``` Kasutame `fetch` API-d, et küsida andmeid serverist asünkroonselt, kuid seekord ei vaja me mingeid lisaparameetreid peale URL-i, kuna küsime ainult andmeid. Vaikimisi loob `fetch` [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET) HTTP-päringu, mis on just see, mida me siin vajame. ✅ `encodeURIComponent()` on funktsioon, mis kodeerib erimärgid URL-i jaoks. Milliseid probleeme võiksime kogeda, kui me ei kutsu seda funktsiooni ja kasutame otse `user` väärtust URL-is? Nüüd uuendame oma `login` funktsiooni, et kasutada `getAccount`: ```js async function login() { const loginForm = document.getElementById('loginForm') const user = loginForm.user.value; const data = await getAccount(user); if (data.error) { return console.log('loginError', data.error); } account = data; navigate('/dashboard'); } ``` Esiteks, kuna `getAccount` on asünkroonne funktsioon, peame selle sobitama `await` märksõnaga, et oodata serveri tulemust. Nagu iga serveripäringu puhul, peame tegelema ka veajuhtumitega. Praegu lisame ainult logisõnumi vea kuvamiseks ja tuleme hiljem selle juurde tagasi. Seejärel peame andmed kuskile salvestama, et saaksime neid hiljem kasutada armatuurlaua teabe kuvamiseks. Kuna `account` muutujat veel ei eksisteeri, loome selle jaoks globaalse muutuja faili ülaosas: ```js let account = null; ``` Pärast kasutajaandmete salvestamist muutujasse saame liikuda *sisselogimise* lehelt *armatuurlauale* kasutades funktsiooni `navigate()`, mis meil juba olemas on. Lõpuks peame kutsuma oma `login` funktsiooni, kui sisselogimisvorm esitatakse, muutes HTML-i: ```html