# Izdelava bančne aplikacije, del 3: Metode pridobivanja in uporabe podatkov Pomislite na računalnik Enterprise v Star Treku – ko kapitan Picard vpraša za stanje ladje, se informacije pojavijo takoj, brez da bi se celoten vmesnik ustavil in znova zgradil. Ta nemoten pretok informacij je natanko tisto, kar tukaj ustvarjamo z dinamičnim pridobivanjem podatkov. Trenutno je vaša bančna aplikacija kot natisnjena časopisna stran – informativna, a statična. Spremenili jo bomo v nekaj bolj podobnega nadzornemu centru NASA, kjer podatki tečejo neprekinjeno in se posodabljajo v realnem času brez prekinjanja delovnega procesa uporabnika. Naučili se boste, kako asinkrono komunicirati s strežniki, upravljati s podatki, ki prispevajo ob različnih časih, in surove informacije preoblikovati v nekaj smiselnemu za vaše uporabnike. To je razlika med pokazno verzijo in programsko opremo, ki je pripravljena za produkcijo. ## ⚡ Kaj lahko naredite v naslednjih 5 minutah **Hitra pot za zaposlene razvijalce** ```mermaid flowchart LR A[⚡ 5 minut] --> B[Nastavi API strežnik] B --> C[Preizkusi pridobivanje s curl] C --> D[Ustvari funkcijo prijave] D --> E[Oglej si podatke v akciji] ``` - **1.–2. minuta**: Zaženite svoj API strežnik (`cd api && npm start`) in preizkusite povezavo - **3. minuta**: Ustvarite osnovno funkcijo `getAccount()` z uporabo fetch - **4. minuta**: Povežite prijavni obrazec z `action="javascript:login()"` - **5. minuta**: Preizkusite prijavo in opazujte podatke o računu v konzoli **Hitri ukazi za testiranje**: ```bash # Preveri, ali API deluje curl http://localhost:5000/api # Preizkusi pridobivanje podatkov računa curl http://localhost:5000/api/accounts/test ``` **Zakaj je to pomembno**: V 5 minutah boste videli magijo asinkronega pridobivanja podatkov, ki poganja vsako moderno spletno aplikacijo. To je temelj, ki aplikacijam daje občutek odzivnosti in živosti. ## 🗺️ Vaša učna pot skozi spletne aplikacije, ki temeljijo na podatkih ```mermaid journey title Od statičnih strani do dinamičnih aplikacij section Razumevanje evolucije Tradicionalno ponovno nalaganje strani: 3: You Odkrijte prednosti AJAX/SPA: 5: You Obvladovanje vzorcev Fetch API: 7: You section Izgradnja avtentikacije Ustvarjanje funkcij za prijavo: 4: You Obvladovanje asinhronih operacij: 6: You Upravljanje uporabniških sej: 8: You section Dinamične posodobitve UI Naučite se manipulacije DOM: 5: You Gradnja prikazov transakcij: 7: You Ustvarjanje odzivnih nadzornih plošč: 9: You section Profesionalni vzorci Renderiranje na osnovi predlog: 6: You Strategije ravnanja z napakami: 7: You Optimizacija uspešnosti: 8: You ``` **Cilj vaše poti**: Do konca te lekcije boste razumeli, kako sodobne spletne aplikacije pridobivajo, obdelujejo in prikazujejo podatke dinamično ter ustvarjajo nemotene uporabniške izkušnje, ki jih pričakujemo od profesionalnih aplikacij. ## Predpredavanje vprašalnik [Predpredavanje vprašalnik](https://ff-quizzes.netlify.app/web/quiz/45) ### Predpogoji Preden se poglobite v pridobivanje podatkov, poskrbite, da imate pripravljene naslednje komponente: - **Pretekla lekcija**: Dokončajte [prijavni in registracijski obrazec](../2-forms/README.md) – na tej podlagi bomo gradili - **Lokalni strežnik**: Namestite [Node.js](https://nodejs.org) in [zaženite API strežnik](../api/README.md), ki zagotavlja podatke o računih - **Povezava z API**: Preizkusite povezavo s strežnikom s tem ukazom: ```bash curl http://localhost:5000/api # Pričakovan odgovor: "Bank API v1.0.0" ``` Ta hiter test zagotavlja pravilno komunikacijo vseh komponent: - Preveri, da Node.js pravilno deluje na vašem sistemu - Potrdi, da je vaš API strežnik aktiven in odziven - Validira, da lahko vaša aplikacija doseže strežnik (kot preverjanje radijskega stika pred misijo) ## 🧠 Pregled ekosistema upravljanja podatkov ```mermaid mindmap root((Upravljanje s podatki)) Authentication Flow Login Process Preverjanje obrazca Preverjanje poverilnic Upravljanje seje User State Globalni račun objekt Varuhi navigacije Obdelava napak API Communication Fetch Patterns GET zahteve POST zahteve Odgovori z napako Data Formats Obdelava JSON Kodiranje URL Razčlenjevanje odgovorov Dynamic UI Updates DOM Manipulation Varen posodobitveni tekst Ustvarjanje elementov Kloniranje predloge User Experience Posodobitve v realnem času Sporočila o napakah Stanja nalaganja Security Considerations XSS Prevention Uporaba textContent Sanitizacija vnosa Varna izdelava HTML CORS Handling Zahteve iz drugih izvorov Konfiguracija glave Nastavitev za razvoj ``` **Osnovno načelo**: Sodobne spletne aplikacije so sistemi za orkestracijo podatkov – usklajujejo uporabniške vmesnike, API strežnike in varnostne modele brskalnikov za ustvarjanje nemotene, odzivne izkušnje. --- ## Razumevanje pridobivanja podatkov v sodobnih spletnih aplikacijah Način, kako spletne aplikacije obvladujejo podatke, se je v zadnjih dveh desetletjih dramatično spremenil. Razumevanje te evolucije vam bo pomagalo ceniti, zakaj so sodobne tehnike, kot sta AJAX in Fetch API, tako zmogljive in zakaj so postale nepogrešljiva orodja za spletne razvijalce. Raziščimo, kako so tradicionalne spletne strani delovale v primerjavi z dinamičnimi, odzivnimi aplikacijami, ki jih danes gradimo. ### Tradicionalne večstranične aplikacije (MPA) V zgodnjih dneh spleta je vsak klik spominjal na menjavo kanalov na stari televiziji – zaslon je potemnil in se počasi osredotočil na novo vsebino. To je bila realnost zgodnjih spletnih aplikacij, kjer je vsak vmesnik pomenil popolno obnovo celotne strani. ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: Klikne povezavo ali pošlje obrazec Browser->>Server: Zahteva novo HTML stran Note over Browser: Stran postane prazna Server->>Browser: Vrne popolno HTML stran Browser->>User: Prikaže novo stran (utrip/osvežitev) ``` ![Delovni proces posodobitve v večstranični aplikaciji](../../../../translated_images/sl/mpa.7f7375a1a2d4aa77.webp) **Zakaj je ta pristop deloval nerodno:** - Vsak klik je pomenil, da je bilo treba znova zgraditi celotno stran od začetka - Uporabniki so bili prekinjeni s temi nadležnimi utripajočimi stranmi - Vaša internetna povezava je delala nadure, saj je večkrat prenašala isti glavi in nogi del strani - Aplikacije so se zdele bolj kot listanje po arhivskih predalih kot uporaba programske opreme ### Sodobne enostranične aplikacije (SPA) AJAX (Asynchronous JavaScript and XML) je to paradigmo popolnoma spremenil. Kot modularna zasnova Mednarodne vesoljske postaje, kjer astronavti lahko zamenjajo posamezne komponente brez obnove celotne strukture, AJAX omogoča posodobitev določenih delov spletne strani brez ponovnega nalaganja vsega. Čeprav ime omenja XML, danes večinoma uporabljamo JSON, vendar osnovno načelo ostaja: posodobi le tisto, kar je treba. ```mermaid sequenceDiagram participant User participant Browser participant JavaScript participant Server User->>Browser: Komunicira s strani Browser->>JavaScript: Sproži obdelovalec dogodkov JavaScript->>Server: Pridobi samo potrebne podatke Server->>JavaScript: Vrne podatke v JSON JavaScript->>Browser: Posodobi specifične elemente strani Browser->>User: Prikaže posodobljeno vsebino (brez osvežitve) ``` ![Delovni proces posodobitve v enostranični aplikaciji](../../../../translated_images/sl/spa.268ec73b41f992c2.webp) **Zakaj so SPA tako prijetne:** - Posodobijo se samo deli, ki so se dejansko spremenili (pametno, kajne?) - Ni več nadležnih prekinitev – uporabniki ostanejo v svojem toku - Manj podatkov potuje po omrežju, kar pomeni hitrejše nalaganje - Vse se zdi odzivno in živahno, kot aplikacije na vašem telefonu ### Evolucija do sodobnega Fetch API Sodobni brskalniki nudijo [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), ki nadomešča starejši [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Tako kot je razlika med upravljanjem telegrafa in uporabo elektronske pošte, Fetch API uporablja obljube (promises) za čistejšo asinhrono kodo in naravno obravnava JSON. | Značilnost | XMLHttpRequest | Fetch API | |------------|----------------|-----------| | **Sintaksa** | Kompleksen, temelji na klicih nazaj | Čista z obljubami (promises) | | **Obdelava JSON** | Ročno razčlenjevanje | Vgrajena metoda `.json()` | | **Obdelava napak** | Omejene informacije o napakah | Celoviti podatki o napakah | | **Sodobna podpora** | Združljivost za ostarele | ES6+ obljube in async/await | > 💡 **Združljivost brskalnikov**: Dobra novica – Fetch API deluje v vseh sodobnih brskalnikih! Če vas zanimajo specifične verzije, ima [caniuse.com](https://caniuse.com/fetch) celotno zgodbo o združljivosti. > **Povzetek:** - Odlično deluje v Chrome, Firefox, Safari in Edge (prakticno kjerkoli, kjer so vaši uporabniki) - Le Internet Explorer potrebuje dodatno pomoč (in iskreno, čas je, da se poslovimo od IE) - Odlično vas pripravi na elegantne vzorce async/await, ki jih bomo uporabljali kasneje ### Implementacija prijave uporabnika in pridobivanje podatkov Zdaj implementirajmo sistem prijave, ki bo vašo bančno aplikacijo spremenil iz statičnega prikaza v funkcionalno aplikacijo. Tako kot avtentikacijski protokoli v varnih vojaških objektih, bomo preverili uporabniške poverilnice in nato ponudili dostop do njihovih specifičnih podatkov. Gradili bomo postopoma, začeli z osnovno avtentikacijo in nato dodali funkcionalnosti za pridobivanje podatkov. #### 1. korak: Ustvarite osnovo funkcije za prijavo Odprite svoje datoteko `app.js` in dodajte novo funkcijo `login`. Ta bo upravljala proces preverjanja uporabnika: ```javascript async function login() { const loginForm = document.getElementById('loginForm'); const user = loginForm.user.value; } ``` **Razčlenimo to:** - Ta ključna beseda `async`? Pove JavaScriptu, da bi ta funkcija lahko čakala na določene stvari - Iz strani pridobimo naš obrazec (nič posebnega, samo ga najdemo po ID-ju) - Nato izvlečemo uporabniško ime, ki ga je uporabnik vnesel - Tukaj je pametni trik: do katerega koli polja v obrazcu lahko dostopate po atributu `name` – ni treba dodatnih klicev getElementById! > 💡 **Vzorec dostopa do obrazca**: Vsak nadzor v obrazcu je dostopen po njegovem imenu (nastavljenem v HTML z atributom `name`) kot lastnost obrazca. To omogoča čist in berljiv način pridobivanja podatkov iz obrazca. #### 2. korak: Ustvarite funkcijo za pridobivanje podatkov o računu Nato bomo ustvarili namensko funkcijo za pridobivanje podatkov o računu s strežnika. Ta sledi istemu vzorcu kot vaša registracijska funkcija, a se osredotoča na pridobivanje podatkov: ```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' }; } } ``` **Kaj ta koda doseže:** - **Uporablja** sodoben fetch API za asinhrono zahtevo podatkov - **Sestavi** GET URL zahtevo z uporabniškim imenom kot parametrom - **Uporabi** `encodeURIComponent()` za varno ravnanje z izjemnimi znaki v URL-ju - **Pretvori** odgovor v JSON format za lažje upravljanje podatkov - **Upravi** napake prijazno tako, da vrne objekt z napako namesto, da se ustavi > ⚠️ **Varnostna opomba**: Funkcija `encodeURIComponent()` varno upravlja posebne znake v URL-jih. Tako kot kodirni sistemi v mornarici zagotavlja, da vaš sporočilo prispe natanko takšno, kot je mišljeno, in preprečuje napačno interpretacijo znakov, kot sta "#" ali "&". > **Zakaj je to pomembno:** - Preprečuje, da posebni znaki prekinejo URL-je - Varuje pred napadi manipulacije URL-jev - Zagotavlja, da strežnik prejme pravilne podatke - Sledi varnim praksam kodiranja #### Razumevanje HTTP GET zahtev Nekaj, kar vas bo morda presenetilo: ko uporabite `fetch` brez dodatnih nastavitev, samodejno ustvari [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET) zahtevo. To je popolno za naš primer – sprašujemo strežnik "hej, lahko vidim podatke za tega uporabnika?" Zahteve GET so kot vljudno prosjenje za izposojo knjige iz knjižnice – zahtevate ogled nečesa obstoječega. POST zahteve (ki smo jih uporabljali za registracijo) so bolj kot oddaja nove knjige za dodajanje v zbirko. | GET zahteva | POST zahteva | |-------------|--------------| | **Namen** | Pridobivanje obstoječih podatkov | Pošiljanje novih podatkov strežniku | | **Parametri** | V URL poti/nizih poizvedb | V telesu zahteve | | **Predpomnjenje** | Lahko predpomnjene v brskalniku | Običajno ne predpomnjene | | **Varnost** | Vidne v URL-jih/zgodovinah | Skrite v telesu zahteve | ```mermaid sequenceDiagram participant B as Brskalnik participant S as Strežnik Note over B,S: GET Zahteva (Pridobivanje podatkov) B->>S: GET /api/accounts/test S-->>B: 200 V REDU + Podatki o računu Note over B,S: POST Zahteva (Oddaja podatkov) B->>S: POST /api/accounts + Novi podatki računa S-->>B: 201 Ustvarjeno + Potrditev Note over B,S: Ravnanje z napakami B->>S: GET /api/accounts/nonexistent S-->>B: 404 Ni najdeno + Sporočilo o napaki ``` #### 3. korak: Združitev vsega skupaj Zdaj za zadovoljiv del – povežimo vašo funkcijo za pridobivanje računa s postopkom prijave. Tu vse začne delovati: ```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'); } ``` Ta funkcija sledi jasnemu zaporedju: - Izvleče uporabniško ime iz obrazca - Zahteva podatke o uporabnikovem računu od strežnika - Obravnava napake, ki se pojavijo med postopkom - Shrani podatke o računu in preusmeri na nadzorno ploščo ob uspehu > 🎯 **Vzorec Async/Await**: Ker je `getAccount` asinhrona funkcija, uporabimo ključni besedi `await`, da zaustavimo izvajanje dokler strežnik ne odgovori. To preprečuje nadaljevanje kode z nedefiniranimi podatki. #### 4. korak: Ustvarite shrambo za vaše podatke Vaša aplikacija potrebuje nekje, da si zapomni informacije o računu, ko so naložene. To je kot kratkoročni spomin vaše aplikacije – prostor za hranjenje trenutnih uporabniških podatkov na dosegu roke. Dodajte to vrstico na vrh datoteke `app.js`: ```javascript // To hrani podatke o trenutnem uporabnikovem računu let account = null; ``` **Zakaj to potrebujemo:** - Omogoča dostop do podatkov o računu od kjerkoli v aplikaciji - Začetek z `null` pomeni "še nihče ni prijavljen" - Posodobi se, ko se nekdo uspešno prijavi ali registrira - Deluje kot enotni vir resnice – brez zmede, kdo je prijavljen #### 5. korak: Povežite svoj obrazec Zdaj povežimo vašo novo prijavno funkcijo z vašim HTML obrazcem. Posodobite oznako obrazca tako: ```html
``` **Kaj ta majhna sprememba naredi:** - Prepreči privzeto vedenje obrazca "osveži celotno stran" - Pokliče vašo prilagojeno JavaScript funkcijo - Ohranja vse gladko, kot enostranska aplikacija - Daje vam popoln nadzor nad tem, kaj se zgodi ob pritisku na "Prijava" #### 6. korak: Izboljšajte svojo registracijsko funkcijo Za doslednost posodobite funkcijo `register`, da tudi shrani podatke o računu in preusmeri na nadzorno ploščo: ```javascript // Na konec vaše funkcije register dodajte te vrstice account = result; navigate('/dashboard'); ``` **Ta izboljšava zagotavlja:** - **Nemoten** prehod od registracije do nadzorne plošče - **Dosledno** uporabniško izkušnjo med prijavo in registracijo - **Neposreden** dostop do podatkov o računu takoj po uspešni registraciji #### Preizkus vaše implementacije ```mermaid flowchart TD A[Uporabnik vnese poverilnice] --> B[Pokličemo funkcijo za prijavo] B --> C[Pridobi podatke računa s strežnika] C --> D{So bili podatki uspešno prejeli?} D -->|Da| E[Shrani podatke računa globalno] D -->|Ne| F[Prikaži sporočilo o napaki] E --> G[Navigiraj na nadzorno ploščo] F --> H[Uporabnik ostane na strani za prijavo] ``` **Čas za testiranje:** 1. Ustvarite nov račun, da potrdite delovanje 2. Poskusite se prijaviti z istimi poverilnicami 3. Pokukajte v konzolo brskalnika (F12), če se kaj ne zdi prav 4. Preverite, da pristanete na nadzorni plošči po uspešni prijavi Če nekaj ne deluje, ne paničarite! Večina težav so enostavne napake, kot so tipkarske napake ali pozaba zagona API strežnika. #### Kratek komentar o čarovniji med domenami Morda se sprašujete: "Kako moja spletna aplikacija komunicira s tem API strežnikom, če te tečejo na različnih vratih?" Odlično vprašanje! To se dotika teme, na katero vsak spletni razvijalec prej ali slej naleti. > 🔒 **Varnost med različnimi izvorji (cross-origin)**: Brskalniki izvajajo "policijo enakega izvora" za preprečevanje nepooblaščenih komunikacij med različnimi domenami. Tako kot nadzorni punkt v Pentagonski zgradbi preverijo, ali je komunikacija pooblaščena, preden dovolijo prenos podatkov. > **V naši postavitvi:** - Vaša spletna aplikacija teče na `localhost:3000` (strežnik za razvoj) - Vaš API strežnik teče na `localhost:5000` (strežnik backend) - API strežnik vključuje [CORS glave](https://developer.mozilla.org/docs/Web/HTTP/CORS), ki izrecno dovoljujejo komunikacijo iz vaše spletne aplikacije Ta nastavitev odraža razvijalno okolje, kjer frontend in backend običajno tečeta na ločenih strežnikih. > 📚 **Več o tem**: Poglobite se v API-je in pridobivanje podatkov z obsežno [Microsoft Learn lekcijo o API-jih](https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=academic-77807-sagibbon). ## Oživitev vaših podatkov v HTML-ju Zdaj bomo pridobljene podatke naredili vidne uporabnikom prek manipulacije z DOM. Tako kot proces razvijanja fotografij v temni sobi, vzamemo nevidne podatke in jih prikažemo kot nekaj, s čimer lahko uporabniki vidno komunicirajo. Manipulacija z DOM-om je tehnika, ki statične spletne strani spremeni v dinamične aplikacije, ki posodabljajo svojo vsebino na podlagi uporabniških interakcij in odzivov strežnika. ### Izbira pravega orodja za delo Ko gre za posodabljanje vašega HTML-ja z JavaScriptom, imate več možnosti. Pomislite na to kot na različna orodja v orodjarni - vsak je popoln za določena opravila: | Metoda | Za kaj je uporabna | Kdaj jo uporabiti | Raven varnosti | |--------|---------------------|------------------|----------------| | `textContent` | Varno prikazovanje uporabniških podatkov | Kadar koli prikazujete besedilo | ✅ Trdno kot skala | | `createElement()` + `append()` | Gradnja zapletenih postavitev | Ustvarjanje novih odsekov/seznamov | ✅ Nezlomljivo | | `innerHTML` | Nastavljanje HTML vsebine | ⚠️ Poskusite se ji izogniti | ❌ Tvegano | #### Varna pot za prikaz besedila: textContent Lastnost [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent) je vaš najboljši prijatelj pri prikazu uporabniških podatkov. Je kot izhodna kontrola za vašo spletno stran - nič škodljivega ne more priti skozi: ```javascript // Varna, zanesljiva metoda za posodabljanje besedila const balanceElement = document.getElementById('balance'); balanceElement.textContent = account.balance; ``` **Prednosti textContent:** - Vse obravnava kot navadno besedilo (preprečuje izvajanje skript) - Samodejno počisti obstoječo vsebino - Učinkovito za preproste posodobitve besedila - Zagotavlja vgrajeno zaščito pred zlonamerno vsebino #### Ustvarjanje dinamičnih HTML elementov Za bolj zapletene vsebine združite [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) z metodo [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append): ```javascript // Varen način za ustvarjanje novih elementov const transactionItem = document.createElement('div'); transactionItem.className = 'transaction-item'; transactionItem.textContent = `${transaction.date}: ${transaction.description}`; container.append(transactionItem); ``` **Razumevanje tega pristopa:** - **Ustvari** nove DOM elemente programsko - **Ohrani** popoln nadzor nad atributi in vsebino elementov - **Omogoča** zapletene, gnezdene strukture elementov - **Ohranja** varnost z ločevanjem strukture od vsebine > ⚠️ **Premislek o varnosti**: Čeprav se [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) pogosto pojavlja v mnogih vodičih, lahko izvršuje vgrajene skripte. Tako kot varnostni protokoli v CERN-u preprečujejo nepooblaščeno izvajanje kode, uporaba `textContent` in `createElement` ponuja varnejše alternative. > **Tveganja innerHTML:** - Izvaja vse `