# Pangaäpi loomine 3. osa: andmete toomise ja kasutamise meetodid Mõtle Star Treki Enterprise'i arvutile – kui kapten Picard küsib laeva olekut, ilmub info koheselt ilma kogu liidese sulgemise ja uuesti ülesehitamiseta. See sujuv infovoog ongi täpselt see, mida me siin dünaamilise andmete toomisega ehitame. Praegu on su pangarakendus nagu trükitud ajaleht – informatiivne, aga staatiline. Muudame selle midagi NASA missioonikontrolli taolisele, kus andmed voolavad pidevalt ja uuenevad reaalajas, katkestamata kasutaja tööd. Õpid suhtlema serveritega asünkroonselt, käsitlema andmeid, mis saabuvad erinevatel aegadel, ning muutma toored andmed millekski tähenduslikuks oma kasutajatele. See on vahe demo ja tootmiseks valmis tarkvara vahel. ## ⚡ Mida saad teha järgmise 5 minutiga **Kiire algus hõivatud arendajatele** ```mermaid flowchart LR A[⚡ 5 minutit] --> B[Seadista API server] B --> C[Testi päringut curliga] C --> D[Loo sisselogimise funktsioon] D --> E[Näe andmeid tegevuses] ``` - **Minut 1-2**: Käivita oma API server (`cd api && npm start`) ja testi ühendus - **Minut 3**: Loo lihtne `getAccount()` funktsioon kasutades fetchi - **Minut 4**: Seosta sisselogimisvorm `action="javascript:login()"` atribuudiga - **Minut 5**: Testi sisselogimist ja jälgi kontode andmete ilmumist konsoolis **Kiired testikäsklused**: ```bash # Kontrolli, kas API töötab curl http://localhost:5000/api # Testkontoga andmete toomine curl http://localhost:5000/api/accounts/test ``` **Miks see oluline on**: 5 minutiga näed asünkroonse andmete toomise maagiat, mis töötab iga kaasaegse veebirakenduse aluseks. See on vundament, mis paneb äppide tunduma kiire ja elusana. ## 🗺️ Sinu õpiteek andmepõhistesse veebirakendustesse ```mermaid journey title Staatilistest lehtedest dünaamiliste rakendusteni section Arengu mõistmine Tavapärased lehe laadimised: 3: You AJAX/SPA eeliste avastamine: 5: You Fetch API mustrite valdamine: 7: You section Autentimise loomine Sisselogimisfunktsioonide loomine: 4: You Asünkroonsete toimingute käsitlemine: 6: You Kasutajasessioonide haldamine: 8: You section Dünaamilised UI uuendused DOM manipuleerimise õppimine: 5: You Tehingute kuvade ehitamine: 7: You Reageerivate juhtpaneelide loomine: 9: You section Professionaalsed mustrid Mallipõhine renderdamine: 6: You Veahaldusstrateegiad: 7: You Tõhususe optimeerimine: 8: You ``` **Õpiteekonnal sihtpunkt**: Selle loengu lõpuks saad aru, kuidas kaasaegsed veebirakendused toovad, töötlevad ja kuvavad andmeid dünaamiliselt, luues professionaalseid kasutajakogemusi, mida me ootame. ## Eelloengu viktoriin [Eelloengu viktoriin](https://ff-quizzes.netlify.app/web/quiz/45) ### Eeldused Enne andmete toomise algust veendu, et sul on valmis järgmised komponendid: - **Eelmine õppetükk**: Lõpeta [Sisselogimis- ja registreerimisvorm](../2-forms/README.md) – ehitame selle peale - **Kohalik server**: Paigalda [Node.js](https://nodejs.org) ja käivita [serveri API](../api/README.md), et pakkuda kontode andmeid - **API ühendus**: Testi oma serveri ühendust selle käsuga: ```bash curl http://localhost:5000/api # Oodatud vastus: "Panga API v1.0.0" ``` See kiire test tagab, et kõik komponendid suhtlevad korrektselt: - Kontrollib, et Node.js töötab su süsteemis õigesti - Kinnitub, et API server on aktiivne ja vastab - Veendub, et sinu äpp saab serveriga ühendust (nagu raadioside kontroll enne missiooni) ## 🧠 Andmehaldussüsteemi ülevaade ```mermaid mindmap root((Andmete Haldamine)) Authentication Flow Login Process Vormi Kontrollimine Tunnuste Kinnitus Seansi Halduse User State Globaalne Konto Objekt Navigatsiooni Kaitse Veahaldus API Communication Fetch Patterns GET Päringud POST Päringud Veavastused Data Formats JSON Töötlemine URL Kodeerimine Vastuse Parseerimine Dynamic UI Updates DOM Manipulation Turvalised Teksti Uuendused Elemendi Loomine Malli Kloonimine User Experience Reaalaja Uuendused Veateated Laadimise Oleku Security Considerations XSS Prevention textContent Kasutus Sisendi Sanitiseerimine Turvalise HTML Loomine CORS Handling Rist-päritolu Päringud Päise Konfiguratsioon Arenduse Seadistamine ``` **Põhiprintsiip**: Kaasaegsed veebirakendused on andmete orkestreerimissüsteemid – nad koordineerivad kasutajaliideseid, serveri API-sid ja brauseri turvemudeleid, et luua sujuvaid ja reageerivaid kogemusi. --- ## Arusaamine andmete toomisest kaasaegsetes veebirakendustes Veebirakenduste viis andmeid käsitleda on viimase kahekümne aastaga oluliselt arenenud. Selle arenguga arusaamine aitab mõista, miks tänapäevased tehnikad nagu AJAX ja Fetch API on nii võimsad ja miks need on saanud veebiarendajate jaoks asendamatuks tööriistaks. Uurime, kuidas traditsioonilised veebilehed töötasid võrreldes dünaamiliste reageerivate rakendustega, mida täna ehitame. ### Traditsioonilised mitmelehelised rakendused (MPA) Veebi algusaegadel oli iga klikkimine nagu telekanalite vahetamine vanas teleris – ekraan läks mustaks ja tihkus aeglaselt uue sisuga täituma. Selline oli varajaste veebirakenduste reaalsus, kus iga tegevus tähendas terve lehe nullist uuesti ülesehitamist. ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: Klikib linki või esitab vormi Browser->>Server: Nõuab uut HTML lehte Note over Browser: Leht muutub tühjaks Server->>Browser: Tagastab täieliku HTML lehe Browser->>User: Kuvab uue lehe (vilgub/laeb uuesti) ```  **Miks see tundus kohmakas:** - Iga klikiga tuli terve leht nullist ehitada - Kasutajate mõtlemine katkestati nende tüütute lehevilkumistega - Su internetiühendus töötas ülekoormatud, laadides ikka ja jälle sama päist ja jalust - Rakendused tundusid pigem kausta sirvimisena kui tarkvara kasutamisena ### Kaasaegsed ühelehelised rakendused (SPA) AJAX (asünkroonne JavaScript ja XML) muutis selle paradigma täielikult. Nagu Rahvusvahelise Kosmosejaama modulaarne ehitus, kus astronaudid saavad vahetada üksikuid komponente ilma kogu struktuuri uuesti ehitmata, võimaldab AJAX meil uuendada veebilehe kindlaid osi ilma kogu lehte uuesti laadimata. Kuigi nimetus sisaldab XML-i, kasutame enamasti JSON-i, aga põhimõte on sama: uuendame ainult seda, mis vajab muutmist. ```mermaid sequenceDiagram participant User participant Browser participant JavaScript participant Server User->>Browser: Suhelda lehega Browser->>JavaScript: Käivitab sündmusekäsitleja JavaScript->>Server: Hangib ainult vajalikke andmeid Server->>JavaScript: Tagastab JSON-andmed JavaScript->>Browser: Uuendab kindlaid lehe elemente Browser->>User: Kuvab uuendatud sisu (ilma taaskäivitamiseta) ```  **Miks SPA-d tunduvad nii palju sujuvamad:** - Uuendatakse ainult neid osi, mis tegelikult muutusid (nutikas, eks?) - Pole enam ebameeldivaid katkestusi – kasutajad jäävad oma voogu - Vähem andmeid liigub üle võrgu, seepärast laadimine on kiirem - Kõik tundub kiirem ja reageerivam, nagu telefoniäpid ### Areng kaasaegse Fetch API-sse Kaasaegsed brauserid pakuvad [`Fetch` API-d](https://developer.mozilla.org/docs/Web/API/Fetch_API), mis asendab vanema [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Nagu mürale kirjutamise ja e-kirja saatmise vahe – Fetch API kasutab lubadusi (promises) puhtama asünkroonse koodi jaoks ning töötab loomulikult JSON-iga. | Omadus | XMLHttpRequest | Fetch API | |---------|----------------|----------| | **Süntaks** | Komplitseeritud tagasikutsumisega | Puhtalt lubadustel põhinev | | **JSON käsitlemine** | Vajab käsitsi parsimist | Sisseehitatud `.json()` meetod | | **Veahaldus** | Piiratud veateave | Ulatuslikud veateated | | **Kaasaegne tugi** | Pärandkompatibliilsus | ES6+ lubadused ja async/await | > 💡 **Brauseri ühildumine**: Hea uudis – Fetch API töötab kõigis kaasaegsetes brauserites! Kui huvitab konkreetne versioon, on täielik ühilduvusloetelu [caniuse.com](https://caniuse.com/fetch). > **Põhitõde:** - Töötab suurepäraselt Chrome, Firefox, Safari ja Edge brauserites (läbi keerulisuse kõikjal, kus su kasutajad on) - Ainult Internet Explorer vajab lisaabi (ja ausalt öeldes on aeg IE-st loobuda) - Valmistab sind hästi ette sujuvaks async/await mustrite kasutamiseks, mida hiljem kasutame ### Kasutaja sisselogimise ja andmete pärimise rakendamine Rakendame nüüd sisselogimissüsteemi, mis muudab su pangarakenduse staatilisest kuvarist funktsionaalseks äpiks. Nagu turvameetmed sõjaväebaaside autentimisel, kontrollime kasutaja volitusi ja seejärel võimaldame ligipääsu nende andmetele. Ehitame selle sammhaaval, alustades põhilisest autentimisest ja seejärel lisades andmete toomise. #### Samm 1: Loo sisselogimisfunktsiooni alus Ava oma `app.js` fail ja lisa uus `login` funktsioon, mis haldab kasutaja autentimist: ```javascript async function login() { const loginForm = document.getElementById('loginForm'); const user = loginForm.user.value; } ``` **Läheme selle läbi:** - See `async` märksõna? See ütleb JavaScriptile: "see funktsioon võib vajada ootamist" - Saame oma vormi lehelt (midagi erilist, leiame selle lihtsalt ID kaudu) - Seejärel võtame välja, mida kasutaja kasutajanime lahtrisse kirjutas - Nüüd üks nipp: igale vormi sisendile pääseb ligi selle `name` atribuudi kaudu – pole vaja keerulist getElementById kutsumist! > 💡 **Vormile ligipääsu muster**: Iga vormikontrolli saab kätte tema nime järgi (HTML-is määratud `name` atribuudi kaudu) kui vormi omaduse – see annab puhta ja loetava võimaluse vormiandmete saamiseks. #### Samm 2: Loo kontoandmete toomise funktsioon Edasi loome pühendatud funktsiooni, mis toob serverist kontoandmeid. See järgib sama mustrit nagu su registreerimisfunktsioon, aga keskendub andmete pärimisele: ```javascript 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' }; } } ``` **See kood teeb järgmist:** - **Kasutab** kaasaegset `fetch` API-d asünkroonseks andmete pärimiseks - **Ehitatakse** GET päringu URL koos kasutajanime parameetriga - **Rakendab** `encodeURIComponent()` funktsiooni, et turvaliselt töödelda erisümboleid URL-is - **Muutab** vastuse JSON-formaati, et hõlpsalt andmeid töödelda - **Haldab** vigu graatsiliselt, tagastades vea objekti, mitte äpi kokkujooksmise > ⚠️ **Turvapähekanne**: `encodeURIComponent()` tagab, et erisümbolid URL-ides ei muutu valeks - nagu sõjalaevade sidekodeeringud, tagab see sõnumi õige kohalejõudmise ja väldib näiteks "#" või "&" vale mõistmist. > **Miks see oluline on:** - Väldib erisümbolitega URL-i rikkeid - Kaitseb URL manipuleerimise rünnakute eest - Tagab, et server saab õige päringu - Järgib turvalise kodeerimise tavasid #### HTTP GET päringute mõistmine Siin on üllatav fakt: kui kasutad `fetch` ilma lisavalikuteta, teeb ta automaatselt [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET) päringu. See sobib meie eesmärgiks – küsida serverilt "palun näita selle kasutaja kontoandmeid". GET päring on nagu viisakas raamatukogust raamatu laenamine – sa palud midagi vaadata, mis juba olemas on. POST päringud (mida kasutasime registreerimisel) on pigem nagu uue raamatu esitlemine kogusse. | GET päring | POST päring | |-------------|-------------| | **Eesmärk** | Oleva andme vaatamine | Uue andme saatmine serverisse | | **Parameetrid** | URL teel/küsimustestringis | Päringu kehas | | **Vahemällu salvestus** | Brauserid võivad vahemällu salvestada | Tavaliselt ei salvestata | | **Turvalisus** | Nähtav URL-is ja logides | Peidetud päringu kehas | ```mermaid sequenceDiagram participant B as Brauser participant S as Server Note over B,S: GET-päring (andmete päring) B->>S: GET /api/accounts/test S-->>B: 200 OK + kontoandmed Note over B,S: POST-päring (andmete saatmine) B->>S: POST /api/accounts + uued kontoandmed S-->>B: 201 Created + kinnitus Note over B,S: Vea käsitlemine B->>S: GET /api/accounts/nonexistent S-->>B: 404 Not Found + veateade ``` #### Samm 3: Kõike kokku toomine Selleks rahuldustpakkuvaks osaks ühenda oma kontoandmete pärimise funktsioon sisselogimise protsessiga. Siin kõik omavahel klapib: ```javascript 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'); } ``` See funktsioon järgib selget järjestust: - Võtab kasutajanime vormi sisendist - Pärib kasutaja kontoandmed serverist - Haldab tekkivaid vigu - Salvestab kontoandmed ja liigub edukal sisselogimisel armatuurlauale > 🎯 **Async/Await muster**: Kuna `getAccount` on asünkroonne, kasutame `await` märksõna, et peatada kood serveri vastuseni ootama. See hoiab ära koodi jooksu määratlemata andmetega. #### Samm 4: Andmete hoidla loomine Su äpil peab olema koht, kuhu kontoandmeid pärast laadimist salvestada – kujutle seda kui äpi lühimälu, kus hoitakse käesoleva kasutaja andmeid. Lisa see rida oma `app.js` faili ülaossa: ```javascript // See hoiab käesoleva kasutaja kontoandmeid let account = null; ``` **Miks seda vaja on:** - Hoiab kontoandmed kättesaadavana igast rakenduse osast - Algväärtus `null` tähendab "keegi pole veel sisse logitud" - Uuendub, kui keegi edukalt sisse logib või registreerub - Toimib tõe ühtse allikana – pole segadust, kes on sisse logitud #### Samm 5: Vormiga ühenduse loomine Ühenda oma äsja loodud sisselogimisfunktsioon HTML vormiga. Uuenda oma vormi sildi nii: ```html
``` **Milleks see väike muudatus:** - Takistab vormil oma vaikekäitumist, mis oleks kogu lehe uuesti laadimine - Kutsutakse selle asemel sinu loodud JavaScripti funktsioon - Tagab sujuva ühelehelise rakenduse kogemuse - Annab täieliku kontrolli selle üle, mis juhtub, kui kasutaja klikib "Login" #### Samm 6: Paranda registreerimisfunktsiooni Ühtlustamiseks uuenda ka oma `register` funktsiooni nii, et salvestatakse kontodata ja liigutakse armatuurlauale: ```javascript // Lisage need read oma registreerimisfunktsiooni lõppu account = result; navigate('/dashboard'); ``` **See täiendus annab:** - **Sujuva** ülemineku registreerimisest armatuurlauale - **Ühtse** kasutajakogemuse nii sisselogimise kui registreerimise protsessides - **Vahetu** ligipääsu kontoandmetele edukal registreerimisel #### Oma koodi testimine ```mermaid flowchart TD A[Kasutaja sisestab mandaadid] --> B[Sisselogimisfunktsioon kutsutud] B --> C[Kontode andmete pärimine serverist] C --> D{Andmed edukalt kätte saadud?} D -->|Jah| E[Kontode andmete globaalne salvestamine] D -->|Ei| F[Vea teate kuvamine] E --> G[Liigu juhtpaneelile] F --> H[Kasutaja jääb sisselogimislehele] ``` **Nüüd aeg proovida:** 1. Loo uus konto, et veenduda, et kõik töötab 2. Proovi nendega sisse logida 3. Kui midagi tundub paigast, vaata brauseri konsooli (F12) 4. Veendu, et pärast edukat sisselogimist jõuad armatuurlauale Kui midagi ei tööta, ära paanitse! Enamik probleeme on lihtsad vead, nagu trükivead või API serveri mittetöölepanemine. #### Kiire märkuse arengutevahelise nõidusest (Cross-Origin) Võib-olla küsid: "Kuidas mu veebirakendus suhtleb API serveriga, kui nad töötavad erinevatel portidel?" Väga hea küsimus! See puudutab midagi, millega iga veebiarendaja kunagi kokku puutub. > 🔒 **Cross-Origin turvalisus**: Brauserid rakendavad "same-origin policy" ehk samu-juurte reeglit, et takistada volitamata side loomist erinevate domeenide vahel. Nagu Pentagoni turvafilter, kontrollitakse sideõigust enne andmete edastamist. > **Meie konfiguratsioonis:** - Sinu veebirakendus jookseb `localhost:3000` (arendusserver) - Sinu API server töötab `localhost:5000` (tagaruumiserver) - API server lisab [CORS pealkirjad](https://developer.mozilla.org/docs/Web/HTTP/CORS), mis lubavad su veebirakendusel temaga suhelda See peegeldab reaalse maailma arendust, kus frontend- ja backend-rakendused tavaliselt jooksevad eraldiseisvatel serveritel. > 📚 **Lisaks lugemiseks**: Süvene API-de ja andmete toomise teemadesse selle põhjaliku [Microsoft Learn mooduli kaudu](https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=academic-77807-sagibbon). ## Andmete elustamine HTML-is Nüüd teeme toodu andmed kasutajatele nähtavaks DOM-i manipuleerimisega. Nagu fotode ilmutamine pimedas ruumis, muudame nähtamatud andmed millekski, mida kasutajad näevad ja millega saavad suhelda. DOM-manipulatsioon on tehnika, mis muudab staatilisi veebilehti dünaamilisteks rakendusteks, mis uuendavad oma sisu kasutaja interaktsioonide ja serveri vastuste põhjal. ### Õige tööriista valimine Kui on vaja HTML-i JavaScripti abil uuendada, on sul mitu võimalust. Mõtle neile kui erinevatele tööriistadele tööriistakastis – igaüks sobib kindlateks töödeks: | Meetod | Milleks see hea on | Millal kasutada | Turvalisuse tase | |--------|---------------------|----------------|--------------| | `textContent` | Kasutaja andmete turvaline kuvamine | Igal ajal, kui näitad teksti | ✅ Kindel | | `createElement()` + `append()` | Komplekssed paigutused | Uute sektsioonide/loendite loomine | ✅ Tõestatud | | `innerHTML` | HTML sisu määramine | ⚠️ Väldi seda võimalust | ❌ Riskantne | #### Turvaline tekstikuvamise viis: textContent [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent) omadus on parim sõber kasutajaandmete kuvamisel. See on nagu turvatöötaja sinu veebilehel – midagi kahjulikku läbi ei saa: ```javascript // Turvaline ja usaldusväärne viis teksti uuendamiseks const balanceElement = document.getElementById('balance'); balanceElement.textContent = account.balance; ``` **textContent eelised:** - Töötleb kõike kui tavalist teksti (takistab skriptide täitmist) - Eemaldab automaatselt olemasoleva sisu - Efektiivne lihtsate tekstiuuenduste jaoks - Pakub sisse ehitatud turvalisust pahatahtliku sisu vastu #### Dünaamiliste HTML-elementide loomine Rohkem keerukama sisu jaoks kombineeri [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) meetodit koos [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append) funktsiooniga: ```javascript // Ohutu viis uute elementide loomiseks const transactionItem = document.createElement('div'); transactionItem.className = 'transaction-item'; transactionItem.textContent = `${transaction.date}: ${transaction.description}`; container.append(transactionItem); ``` **Selle lähenemise mõistmine:** - **Loob** DOM-elemente programmiliselt - **Hoiab** täielikku kontrolli elementide atribuutide ja sisu üle - **Võimaldab** keerukaid, pesastatud elementide struktuure - **Säilitab** turvalisuse, eraldades struktuuri sisust > ⚠️ **Turvaküsimus**: Kuigi [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) on paljudes juhendites, võib see täita leitud skripte. Nagu CERN-i turvaprotokollid keelavad volitamata koodide käivitamise, pakuvad `textContent` ja `createElement` turvalisemaid alternatiive. > **innerHTML riskid:** - Täidab kasutajaandmetes olevad `