# Banki alkalmazás készítése 3. rész: Az adatok lekérésének és használatának módszerei Gondolj az Enterprise számítógépére a Star Trekből – amikor Picard kapitány megkéri az állapotjelentést, az információ azonnal megjelenik anélkül, hogy az egész felület leállna és újraépülne. Pont ezt a zökkenőmentes adatáramlást építjük most dinamikus adatlekéréssel. Most a banki alkalmazásod olyan, mint egy nyomtatott újság – információgazdag, de statikus. Átalakítjuk olyanná, mint a NASA parancsnoki központja, ahol az adatok folyamatosan, valós időben frissülnek anélkül, hogy megzavarnák a felhasználó munkafolyamatát. Megtanulod, hogyan kommunikálj aszinkron módon a szerverrel, kezelni az eltérő időben érkező adatokat, és hogyan alakítsd át a nyers információt valami értékessé a felhasználók számára. Ez a különbség a demó és a gyártásra kész szoftver között. ## ⚡ Amit a következő 5 percben megtehetsz **Gyors indítás elfoglalt fejlesztőknek** ```mermaid flowchart LR A[⚡ 5 perc] --> B[API szerver beállítása] B --> C[Fetch tesztelése curl-lel] C --> D[Bejelentkezési funkció létrehozása] D --> E[Adatok működés közben] ``` - **1-2. perc**: Indítsd el az API szervert (`cd api && npm start`), és teszteld a kapcsolatot - **3. perc**: Hozz létre egy alap `getAccount()` függvényt fetch használatával - **4. perc**: Kapcsold össze a bejelentkező űrlapot az `action="javascript:login()"` attribútummal - **5. perc**: Teszteld a bejelentkezést, és figyeld meg, ahogy a fiókadatok megjelennek a konzolon **Gyors teszt parancsok**: ```bash # Ellenőrizze, hogy az API fut-e curl http://localhost:5000/api # Tesztelje a fiókadatok lekérését curl http://localhost:5000/api/accounts/test ``` **Miért fontos ez?** 5 perc alatt megtapasztalod az aszinkron adatlekérés varázsát, amely a modern webalkalmazások motorja. Ez az alapja annak, hogy az appok reszponzívnak és élőnek érezzék magukat. ## 🗺️ Tanulási utad adatvezérelt webalkalmazásokkal ```mermaid journey title Statikus lapoktól a dinamikus alkalmazásokig section Az evolúció megértése Hagyományos oldalfrissítések: 3: You AJAX/SPA előnyeinek felfedezése: 5: You Fetch API minták elsajátítása: 7: You section Hitelesítés felépítése Bejelentkező funkciók létrehozása: 4: You Aszinkron műveletek kezelése: 6: You Felhasználói munkamenetek kezelése: 8: You section Dinamikus UI frissítések DOM manipuláció tanulása: 5: You Tranzakciós megjelenítések készítése: 7: You Reszponzív irányítópultok létrehozása: 9: You section Professzionális minták Template alapú renderelés: 6: You Hibakezelési stratégiák: 7: You Teljesítmény optimalizálás: 8: You ``` **Utazásod célja**: A lecke végére megérted, hogyan kérnek le, dolgoznak fel és jelenítenek meg adatokat a modern webalkalmazások dinamikusan, létrehozva az általunk elvárt zökkenőmentes felhasználói élményeket. ## Előzetes kvíz [Előadó előtti kvíz](https://ff-quizzes.netlify.app/web/quiz/45) ### Előfeltételek Mielőtt belevágnál az adatlekérésbe, győződj meg róla, hogy ezek az összetevők készen állnak: - **Előző lecke**: Készítsd el a [Bejelentkező és regisztrációs űrlapot](../2-forms/README.md) – erre építünk majd tovább - **Helyi szerver**: Telepítsd a [Node.js-t](https://nodejs.org) és [indítsd el az API szervert](../api/README.md), hogy szolgáltassa a fiókadatokat - **API kapcsolat**: Teszteld a szerver kapcsolatot ezzel a paranccsal: ```bash curl http://localhost:5000/api # Várt válasz: "Bank API v1.0.0" ``` Ez a gyors teszt biztosítja a kommunikációt: - Ellenőrzi, hogy a Node.js helyesen fut a gépeden - Megerősíti, hogy az API szerver aktív és válaszol - Érvényesíti, hogy az app eléri a szervert (mint rádiókapcsolat ellenőrzése a küldetés előtt) ## 🧠 Adatkezelési rendszer áttekintése ```mermaid mindmap root((Adatkezelés)) Authentication Flow Login Process Form Validation Credential Verification Session Management User State Global Account Object Navigation Guards Error Handling API Communication Fetch Patterns GET Requests POST Requests Error Responses Data Formats JSON Processing URL Encoding Response Parsing Dynamic UI Updates DOM Manipulation Safe Text Updates Element Creation Template Cloning User Experience Real-time Updates Error Messages Loading States Security Considerations XSS Prevention textContent Usage Input Sanitization Safe HTML Creation CORS Handling Cross-Origin Requests Header Configuration Development Setup ``` **Alapelvek**: A modern webalkalmazások adat-orchestrációs rendszerek – koordinálják a felhasználói felületet, a szerver API-kat és a böngésző biztonsági modelljét, hogy zökkenőmentes, reszponzív élményeket alkossanak. --- ## Az adatlekérés megértése a modern webalkalmazásokban Az elmúlt két évtizedben drámaian fejlődött, ahogyan a webalkalmazások kezelik az adatokat. Az evolúció megértése segít értékelni, miért olyan erőteljesek a mai AJAX és Fetch API technikák, és miért váltak elengedhetetlen eszközökké a fejlesztők számára. Vizsgáljuk meg, hogyan működtek a hagyományos weboldalak a mai dinamikus, reszponzív alkalmazásokhoz képest. ### Hagyományos, sokoldalas alkalmazások (MPA) A web korai napjaiban minden kattintás olyan volt, mint a tévécsatorna váltás – a képernyő elsötétült, majd lassan töltődött be az új tartalom. Ez volt a korai webalkalmazások valósága, ahol minden interakció az egész oldal teljes újraépítését jelentette. ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: Kattint a linkre vagy elküldi az űrlapot Browser->>Server: Új HTML oldal kérése Note over Browser: Az oldal üressé válik Server->>Browser: Teljes HTML oldalt ad vissza Browser->>User: Megjeleníti az új oldalt (villanás/újratöltés) ``` ![Frissítési folyamat sokoldalas alkalmazásban](../../../../translated_images/hu/mpa.7f7375a1a2d4aa77.webp) **Miért volt kényelmetlen ez az eljárás:** - Minden kattintás az egész oldal újraépítését jelentette - A felhasználók közbeszakadtak a gondolataikban a zavaró oldal-frissítések miatt - A netkapcsolat túlórázott, mert folyton letöltötte ugyanazt a fejlécet és láblécet - Az appok inkább fájlszekrények között való kattintgatáshoz hasonlítottak, mint szoftverhasználathoz ### Modern egylapos alkalmazások (SPA) Az AJAX (Asynchronous JavaScript and XML) teljesen megváltoztatta ezt a paradigmát. Olyan, mint a Nemzetközi Űrállomás moduláris felépítése, ahol az asztronauták tudják cserélni az egyes részegységeket anélkül, hogy az egészet újraépítenék – az AJAX lehetővé teszi, hogy egy weboldal adott részeit frissítsük újratöltés nélkül. Az elnevezés XML-t említ, de ma főként JSON-t használunk, a lényeg az, hogy csak azt frissítjük, ami változott. ```mermaid sequenceDiagram participant User participant Browser participant JavaScript participant Server User->>Browser: Kapcsolódik az oldalhoz Browser->>JavaScript: Eseménykezelő aktiválása JavaScript->>Server: Csak a szükséges adatokat kéri le Server->>JavaScript: JSON adatokat küld vissza JavaScript->>Browser: Frissíti a konkrét oldal elemeket Browser->>User: Megjeleníti a frissített tartalmat (újratöltés nélkül) ``` ![Frissítési folyamat egylapos alkalmazásban](../../../../translated_images/hu/spa.268ec73b41f992c2.webp) **Miért jobb az SPA:** - Csak a ténylegesen változott részek frissülnek (okosan, ugye?) - Nincs több menet közbeni megszakítás – a felhasználók áramlásban maradnak - Kevesebb adat utazik, gyorsabb a betöltés - Minden gyors és reszponzív érzésű, mint a telefonodon futó appok ### Az áttérés a modern Fetch API-ra A modern böngészők biztosítják a [`Fetch` API-t](https://developer.mozilla.org/docs/Web/API/Fetch_API), amely leváltotta a régebbi [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest) megoldást. Mint a távíró és az email különbsége, a Fetch ígéreteket használ a tisztább aszinkron kódért, és natívan kezeli a JSON-t. | Tulajdonság | XMLHttpRequest | Fetch API | |-------------|----------------|-----------| | **Szintaxis** | Bonyolult callback alapú | Tiszta promise alapú | | **JSON kezelés** | Kézi feldolgozás szükséges | Beépített `.json()` metódus | | **Hiba kezelés** | Korlátozott hibainformáció | Részletes hibakezelés | | **Modern támogatás** | Legacy kompatibilitás | ES6+ ígéretek és async/await | > 💡 **Böngésző kompatibilitás**: Jó hír – a Fetch API működik minden modern böngészőben! Ha kíváncsi vagy adott verziókra, [caniuse.com](https://caniuse.com/fetch) teljes kompatibilitási táblázatot nyújt. > **Összefoglalva:** - Jól működik Chrome-ban, Firefox-ban, Safari-ban és Edge-ben (ahol a felhasználóid is vannak) - Csak az Internet Explorer igényel plusz támogatást (Őszintén, ideje elengedni az IE-t) - Tökéletes alapot ad az elegáns async/await mintákhoz, amiket még látni fogunk ### Felhasználói bejelentkezés és adatlekérés megvalósítása Most valósítsuk meg a bejelentkező rendszert, amely a statikus megjelenítésből funkcionális alkalmazást varázsol. Mint a biztonságos katonai létesítmények hitelesítési protokolljai, ellenőrizzük a felhasználó adatait, majd hozzáférést adunk a személyes fiókadataihoz. Fokozatosan építjük fel: először a hitelesítés, aztán az adatlekérés funkciókat. #### 1. lépés: A bejelentkező függvény alapja Nyisd meg az `app.js` fájlodat, és adj hozzá egy új `login` függvényt, amely kezeli a felhasználó hitelesítését: ```javascript async function login() { const loginForm = document.getElementById('loginForm'); const user = loginForm.user.value; } ``` **Íme a bontás:** - Az `async` kulcsszó azt jelzi a JavaScriptnek, hogy várakoznia kellhet - Kikeressük az űrlapot az oldalon (semmi extra, csak az ID alapján) - Kiolvassuk a felhasználónév értékét - Egy praktikus trükk: bármely űrlapelemhez hozzáférhetsz a `name` attribútumán keresztül – nem kell plusz getElementById hívás! > 💡 **Űrlap elérési minta**: Minden űrlapvezérlőhöz hozzáférsz a `name` attribútum alapján, az űrlap elem tulajdonságaként. Ez átlátható, tiszta mód az adatkinyeréshez. #### 2. lépés: Az adatlekérő függvény létrehozása Készítsünk egy külön függvényt a fiókadatok szerverről való lekérésére. Ez hasonló a regisztrációs funkcióhoz, de most az adatokat kérjük le: ```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' }; } } ``` **Mit csinál ez a kód:** - **Használ** modernebb `fetch` API-t az aszinkron adatlekéréshez - **Összerak** egy GET kérést a felhasználónév paraméterével - **Használja** az `encodeURIComponent()`-ot az URL speciális karaktereinek biztonságos kezelésére - **Átalakítja** a választ JSON formátummá az egyszerű adatkezelés miatt - **Kezeletlenül kezeli** a hibákat, hibaobjektummal tér vissza, nem omlik össze > ⚠️ **Biztonsági megjegyzés**: Az `encodeURIComponent()` védi az URL-ben szereplő speciális karaktereket. Mint egy haditengerészeti kódolási rendszer, megakadályozza, hogy a `#` vagy `&` karakterek rossz értelmezést kapjanak. > **Miért fontos:** - Megakadályozza, hogy speciális karakterek tönkretegyék az URL-t - Védekezik az URL manipulációs támadások ellen - Biztosítja, hogy a szerver pontosan megkapja az adatot - Követi a biztonságos kódolási gyakorlatokat #### HTTP GET kérések megértése Valami, ami talán meglep: ha fetch-t használunk opciók nélkül, automatikusan egy [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET) kérést készít. Ez tökéletes arra, hogy megkérjük a szervert: „Mutasd a felhasználó fiókadatait!” Gondolj a GET-re úgy, mintha udvariasan kölcsönkérnél egy könyvet a könyvtárból – már létező adatot kérsz. A POST (amit a regisztrációhoz használtunk) inkább új könyv beadásához hasonlít. | GET kérés | POST kérés | |-----------|------------| | **Cél** | Meglévő adat lekérése | Új adat elküldése a szerverre | | **Paraméterek** | URL-ben/kérdésben | Kérés törzsében | | **Gyorsítótár** | Böngésző gyorsítótárazhatja | Általában nem gyorsítótárazott | | **Biztonság** | Látható az URL-ben/naplókban | El van rejtve a kérés törzsében | ```mermaid sequenceDiagram participant B as Böngésző participant S as Szerver Note over B,S: GET Kérés (Adatlekérés) B->>S: GET /api/accounts/test S-->>B: 200 OK + Fiókadatok Note over B,S: POST Kérés (Adatbeküldés) B->>S: POST /api/accounts + Új fiók adatai S-->>B: 201 Created + Visszaigazolás Note over B,S: Hibakezelés B->>S: GET /api/accounts/nonexistent S-->>B: 404 Nem található + Hibaüzenet ``` #### 3. lépés: Összekapcsolás Most jön a lényeg: csatlakoztassuk a fiókadat lekérő függvényt a bejelentkezéshez. Itt áll össze minden: ```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'); } ``` Ez a függvény világos sorrendet követ: - Kimenti a felhasználónevet az űrlapról - Lekéri a fiókadatokat a szerverről - Kezeli az esetleges hibákat - Siker esetén eltárolja az adatokat és a műszerfalra navigál > 🎯 **Async/Await minta**: Mivel `getAccount` aszinkron, használjuk az `await` kulcsszót, hogy várjon a válaszra, így ne folytassa a kódot nem definiált adatokkal. #### 4. lépés: Hol tároljuk az adatokat? Az appnak kell valami „rövid távú memóriája”, ahol megtartja a beolvasott adatokat. Ezt helyezd az `app.js` tetejére: ```javascript // Ez tárolja az aktuális felhasználó fiókadatait let account = null; ``` **Miért van erre szükség:** - Mindenhol hozzáférhetővé teszi az aktuális adatokat - Kezdőérték `null`, ami azt jelenti: „még senki nincs bejelentkezve” - Frissítve lesz bejelentkezés vagy regisztráció után - Központi forrásként szolgál – egyértelmű, ki van bejelentkezve #### 5. lépés: Kapcsold be az űrlapot Most kösd össze az űrlapot az új login függvénnyel. Módosítsd az űrlap címkéjét: ```html
``` **Mit tesz ez a kis módosítás:** - Meggátolja az űrlapot abban, hogy újratöltse az egész oldalt - Ezzel helyette a saját JavaScript függvényedet hívja meg - Minden simán, egylapos-alkalmazásszerűen történik - Teljes kontrollt ad, mi történjen a bejelentkezéskor #### 6. lépés: Regisztrációs funkció bővítése Az egységesség kedvéért frissítsd a `register` függvényt is, hogy eltárolja az adatokat és a műszerfalra navigáljon: ```javascript // Add hozzá ezeket a sorokat a register függvényed végéhez account = result; navigate('/dashboard'); ``` **Ez a bővítés biztosítja:** - **Zökkenőmentes** átmenet regisztráció után a műszerfalra - **Egységes** felhasználói élmény bejelentkezés és regisztráció között - **Azonnali** hozzáférést a fiókadatokhoz sikeres regisztráció után #### Teszteld az implementációt ```mermaid flowchart TD A[Felhasználó megadja a hitelesítő adatokat] --> B[Bejelentkező függvény hívása] B --> C[Fiókadatok lekérése a szerverről] C --> D{Az adatok sikeresen megérkeztek?} D -->|Igen| E[Fiókadatok globális tárolása] D -->|Nem| F[Hibaüzenet megjelenítése] E --> G[Átnavigálás a műszerfalra] F --> H[Felhasználó a bejelentkező oldalon marad] ``` **Itt az idő kipróbálni:** 1. Hozz létre új fiókot, hogy megbizonyosodj a működésről 2. Jelentkezz be ezekkel az adatokkal 3. Nézd meg a böngésző konzolt (F12), ha valami nem stimmel 4. Ellenőrizd, hogy a sikeres bejelentkezés után a műszerfalra kerülsz-e Ha valami nem működik, ne ess pánikba! A legtöbb hibát elírás vagy az API szerver el nem indítása okozza. #### Egy gyors szó a cross-origin varázslatról Lehet, hogy érdekel: "Hogy beszél a webalkalmazásom a másik porton futó API szerverrel?" Ez egy általános kérdés, ami minden webfejlesztőt előbb-utóbb foglalkoztat. > 🔒 **Cross-Origin biztonság**: A böngészők “same-origin policy”-t alkalmaznak, hogy megelőzzék a jogosulatlan kommunikációt. Mint a Pentagon ellenőrző pontja, letesztelik, hogy engedélyezett-e az adatátvitel. > **A mi esetünkben:** - A webappod a `localhost:3000` címen fut (fejlesztői szerver) - Az API szerver a `localhost:5000` címen fut (backend) - Az API szerver CORS fejléceket alkalmaz, melyek engedélyezik a kommunikációt a webalkalmazásodtól Ez tükrözi a valós fejlesztői környezetet, ahol front- és backend külön szervereken fut. > 📚 **További tanulás**: Mélyedj el az API-k és adatlekérés témakörében a [Microsoft Learn részletes moduljában API-król](https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=academic-77807-sagibbon). ## Az adatok életre keltése HTML-ben Most megjelenítjük a lekért adatokat a felhasználóknak a DOM manipuláció segítségével. Olyan, mintha a fényképeket kidolgoznánk a sötétkamrában – az eddig láthatatlan adatokat valami láthatóvá és használhatóvá alakítjuk. A DOM manipuláció az a technika, amely statikus weboldalakat dinamikus alkalmazásokká alakít, amelyek a felhasználói interakciók és a szerver válaszai alapján frissítik tartalmukat. ### A megfelelő eszköz kiválasztása a feladathoz Amikor a HTML-edet JavaScript-tel szeretnéd frissíteni, több lehetőséged van. Gondolj ezekre úgy, mint egy szerszámosládában lévő különféle szerszámokra – mindegyik tökéletes bizonyos feladatokhoz: | Módszer | Mire jó | Mikor használd | Biztonsági szint | |---------|---------|----------------|------------------| | `textContent` | Felhasználói adatok biztonságos megjelenítése | Bármikor, amikor szöveget jelenítesz meg | ✅ Sziklaszilárd | | `createElement()` + `append()` | Összetett elrendezések építése | Új szekciók/listák létrehozásához | ✅ Több sebből vérzik | | `innerHTML` | HTML tartalom beállítása | ⚠️ Próbáld meg kerülni | ❌ Kockázatos | #### Szöveg biztonságos megjelenítése: textContent A [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent) tulajdonság a legjobb barátod, amikor felhasználói adatokat szeretnél megjeleníteni. Olyan, mint egy kidobó az oldaladon – semmi káros nem jut át: ```javascript // A szöveg biztonságos, megbízható frissítési módja const balanceElement = document.getElementById('balance'); balanceElement.textContent = account.balance; ``` **A textContent előnyei:** - Minden elemet egyszerű szövegként kezel (megakadályozza a szkriptek futtatását) - Automatikusan törli a meglévő tartalmat - Hatékony egyszerű szövegfrissítéshez - Beépített védelem a rosszindulatú tartalom ellen #### Dinamikus HTML elemek létrehozása Összetettebb tartalomhoz kombináld a [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) metódust az [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append) módszerrel: ```javascript // Biztonságos módja új elemek létrehozásának const transactionItem = document.createElement('div'); transactionItem.className = 'transaction-item'; transactionItem.textContent = `${transaction.date}: ${transaction.description}`; container.append(transactionItem); ``` **Az eljárás megértése:** - **Új** DOM elemeket hoz létre programozottan - **Teljes** kontrollt biztosít az elem attribútumai és tartalma felett - **Lehetővé** teszi összetett, egymásba ágyazott elemszerkezetek létrehozását - **Megőrzi** a biztonságot azáltal, hogy szétválasztja a szerkezetet a tartalomtól > ⚠️ **Biztonsági megfontolás**: Bár az [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) sok oktatóanyagban előfordul, képes végrehajtani beágyazott szkripteket. Akárcsak a CERN biztonsági protokolljai, amelyek megakadályozzák az illetéktelen kódvégrehajtást, a `textContent` és `createElement` használata biztonságosabb alternatívákat nyújt. > **Az innerHTML kockázatai:** - Végrehajt minden `