# Construirea unei aplicații bancare Partea 3: Metode de preluare și utilizare a datelor Gândește-te la computerul Enterprise din Star Trek - când căpitanul Picard cere starea navei, informațiile apar instantaneu fără ca întreaga interfață să se oprească și să se reconstruiască. Acest flux fluid de informații este exact ceea ce construim aici, prin preluarea dinamică a datelor. În momentul de față, aplicația ta bancară este ca un ziar tipărit - informativ, dar static. O vom transforma în ceva asemănător cu centrul de control al misiunilor NASA, unde datele circulă continuu și se actualizează în timp real fără a întrerupe fluxul de lucru al utilizatorului. Vei învăța cum să comunici cu serverele în mod asincron, să gestionezi datele care sosesc la momente diferite și să transformi informațiile brute în ceva semnificativ pentru utilizatorii tăi. Aceasta este diferența dintre o demonstrație și un software pregătit pentru producție. ## Chestionar înainte de lecție [Chestionar înainte de lecție](https://ff-quizzes.netlify.app/web/quiz/45) ### Cerințe preliminare Înainte de a începe cu preluarea datelor, asigură-te că ai următoarele componente pregătite: - **Lecția anterioară**: Finalizează [Formularul de autentificare și înregistrare](../2-forms/README.md) - vom construi pe baza acestui fundament - **Server local**: Instalează [Node.js](https://nodejs.org) și [rulează API-ul serverului](../api/README.md) pentru a furniza datele contului - **Conexiune API**: Testează conexiunea serverului cu această comandă: ```bash curl http://localhost:5000/api # Expected response: "Bank API v1.0.0" ``` Acest test rapid asigură că toate componentele comunică corect: - Verifică dacă Node.js funcționează corect pe sistemul tău - Confirmă că serverul API este activ și răspunde - Validează că aplicația ta poate accesa serverul (ca verificarea contactului radio înainte de o misiune) --- ## Înțelegerea preluării datelor în aplicațiile web moderne Modul în care aplicațiile web gestionează datele a evoluat dramatic în ultimele două decenii. Înțelegerea acestei evoluții te va ajuta să apreciezi de ce tehnici moderne precum AJAX și Fetch API sunt atât de puternice și de ce au devenit instrumente esențiale pentru dezvoltatorii web. Să explorăm cum funcționau site-urile tradiționale comparativ cu aplicațiile dinamice și responsive pe care le construim astăzi. ### Aplicații tradiționale multi-pagină (MPA) În primele zile ale web-ului, fiecare clic era ca schimbarea canalelor pe un televizor vechi - ecranul se golea, apoi se regla încet pe noul conținut. Aceasta era realitatea aplicațiilor web timpurii, unde fiecare interacțiune însemna reconstruirea completă a paginii de la zero. ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: Clicks link or submits form Browser->>Server: Requests new HTML page Note over Browser: Page goes blank Server->>Browser: Returns complete HTML page Browser->>User: Displays new page (flash/reload) ``` ![Fluxul de actualizare într-o aplicație multi-pagină](../../../../translated_images/mpa.7f7375a1a2d4aa779d3f928a2aaaf9ad76bcdeb05cfce2dc27ab126024050f51.ro.png) **De ce această abordare părea greoaie:** - Fiecare clic însemna reconstruirea completă a paginii de la zero - Utilizatorii erau întrerupți în mijlocul gândurilor de acele flash-uri enervante ale paginii - Conexiunea ta la internet lucra excesiv descărcând același antet și subsol în mod repetat - Aplicațiile păreau mai mult ca navigarea printr-un dosar decât utilizarea unui software ### Aplicații moderne cu o singură pagină (SPA) AJAX (JavaScript și XML asincron) a schimbat complet acest paradigm. La fel ca designul modular al Stației Spațiale Internaționale, unde astronauții pot înlocui componente individuale fără a reconstrui întreaga structură, AJAX ne permite să actualizăm părți specifice ale unei pagini web fără a reîncărca totul. Deși numele menționează XML, astăzi folosim în principal JSON, dar principiul de bază rămâne: actualizează doar ceea ce trebuie să se schimbe. ```mermaid sequenceDiagram participant User participant Browser participant JavaScript participant Server User->>Browser: Interacts with page Browser->>JavaScript: Triggers event handler JavaScript->>Server: Fetches only needed data Server->>JavaScript: Returns JSON data JavaScript->>Browser: Updates specific page elements Browser->>User: Shows updated content (no reload) ``` ![Fluxul de actualizare într-o aplicație cu o singură pagină](../../../../translated_images/spa.268ec73b41f992c2a21ef9294235c6ae597b3c37e2c03f0494c2d8857325cc57.ro.png) **De ce SPA-urile sunt mai bune:** - Doar părțile care s-au schimbat efectiv sunt actualizate (inteligent, nu?) - Fără întreruperi deranjante - utilizatorii rămân concentrați - Mai puține date care circulă pe rețea înseamnă încărcare mai rapidă - Totul se simte rapid și receptiv, la fel ca aplicațiile de pe telefonul tău ### Evoluția către API-ul modern Fetch Browserele moderne oferă [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), care înlocuiește vechiul [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). La fel ca diferența dintre operarea unui telegraf și utilizarea e-mailului, Fetch API folosește promisiuni pentru un cod asincron mai curat și gestionează JSON în mod natural. | Caracteristică | XMLHttpRequest | Fetch API | |----------------|----------------|-----------| | **Sintaxă** | Bazată pe callback-uri complexe | Bazată pe promisiuni clare | | **Gestionarea JSON** | Necesită analiză manuală | Metoda încorporată `.json()` | | **Gestionarea erorilor** | Informații limitate despre erori | Detalii complete despre erori | | **Suport modern** | Compatibilitate cu versiuni vechi | Promisiuni ES6+ și async/await | > 💡 **Compatibilitate cu browserele**: Veste bună - Fetch API funcționează în toate browserele moderne! Dacă ești curios despre versiuni specifice, [caniuse.com](https://caniuse.com/fetch) are toate detaliile despre compatibilitate. > **Concluzia:** - Funcționează excelent în Chrome, Firefox, Safari și Edge (practic peste tot unde sunt utilizatorii tăi) - Doar Internet Explorer are nevoie de ajutor suplimentar (și sincer, e timpul să renunțăm la IE) - Te pregătește perfect pentru modelele elegante async/await pe care le vom folosi mai târziu ### Implementarea autentificării utilizatorului și preluarea datelor Acum să implementăm sistemul de autentificare care transformă aplicația ta bancară dintr-un afișaj static într-o aplicație funcțională. La fel ca protocoalele de autentificare utilizate în facilitățile militare securizate, vom verifica acreditările utilizatorului și apoi vom oferi acces la datele specifice ale acestuia. Vom construi acest lucru treptat, începând cu autentificarea de bază și apoi adăugând capacitățile de preluare a datelor. #### Pasul 1: Crearea funcției de bază pentru autentificare Deschide fișierul `app.js` și adaugă o nouă funcție `login`. Aceasta va gestiona procesul de autentificare al utilizatorului: ```javascript async function login() { const loginForm = document.getElementById('loginForm'); const user = loginForm.user.value; } ``` **Să descompunem acest lucru:** - Cuvântul cheie `async`? Spune JavaScript-ului "hei, această funcție ar putea avea nevoie să aștepte lucruri" - Luăm formularul de pe pagină (nimic sofisticat, doar îl găsim după ID-ul său) - Apoi extragem ceea ce utilizatorul a tastat ca nume de utilizator - Iată un truc interesant: poți accesa orice câmp de formular prin atributul său `name` - nu este nevoie de apeluri suplimentare getElementById! > 💡 **Model de acces la formular**: Fiecare control al formularului poate fi accesat prin numele său (setat în HTML folosind atributul `name`) ca proprietate a elementului formularului. Acest lucru oferă o modalitate curată și ușor de citit pentru a obține datele din formular. #### Pasul 2: Crearea funcției de preluare a datelor contului În continuare, vom crea o funcție dedicată pentru a prelua datele contului de la server. Aceasta urmează același model ca funcția de înregistrare, dar se concentrează pe preluarea datelor: ```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' }; } } ``` **Ce realizează acest cod:** - **Folosește** API-ul modern `fetch` pentru a solicita date în mod asincron - **Construiește** un URL de cerere GET cu parametrul de nume de utilizator - **Aplică** `encodeURIComponent()` pentru a gestiona în siguranță caracterele speciale din URL-uri - **Transformă** răspunsul în format JSON pentru manipularea ușoară a datelor - **Gestionează** erorile în mod elegant, returnând un obiect de eroare în loc să se blocheze > ⚠️ **Notă de securitate**: Funcția `encodeURIComponent()` gestionează caracterele speciale din URL-uri. La fel ca sistemele de codificare utilizate în comunicațiile navale, asigură că mesajul tău ajunge exact așa cum a fost intenționat, prevenind interpretarea greșită a caracterelor precum "#" sau "&". > **De ce contează:** - Previne ca caracterele speciale să strice URL-urile - Protejează împotriva atacurilor de manipulare a URL-urilor - Asigură că serverul primește datele intenționate - Urmează practici de codare securizate #### Înțelegerea cererilor HTTP GET Iată ceva ce te-ar putea surprinde: când folosești `fetch` fără opțiuni suplimentare, creează automat o cerere [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET). Acest lucru este perfect pentru ceea ce facem - cerem serverului "hei, pot să văd datele contului acestui utilizator?" Gândește-te la cererile GET ca la cererea politicosă de a împrumuta o carte de la bibliotecă - soliciți să vezi ceva ce există deja. Cererile POST (pe care le-am folosit pentru înregistrare) sunt mai mult ca trimiterea unei noi cărți pentru a fi adăugată în colecție. | Cerere GET | Cerere POST | |------------|-------------| | **Scop** | Preluarea datelor existente | Trimiterea de date noi către server | | **Parametri** | În calea URL/șirul de interogare | În corpul cererii | | **Caching** | Poate fi stocată în cache de browsere | De obicei, nu este stocată în cache | | **Securitate** | Vizibilă în URL/jurnale | Ascunsă în corpul cererii | #### Pasul 3: Punerea tuturor lucrurilor împreună Acum partea satisfăcătoare - să conectăm funcția de preluare a datelor contului la procesul de autentificare. Aici totul se leagă: ```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'); } ``` Această funcție urmează o secvență clară: - Extrage numele de utilizator din câmpul de introducere al formularului - Solicită datele contului utilizatorului de la server - Gestionează orice erori care apar în timpul procesului - Stochează datele contului și navighează la tabloul de bord în caz de succes > 🎯 **Modelul Async/Await**: Deoarece `getAccount` este o funcție asincronă, folosim cuvântul cheie `await` pentru a opri execuția până când serverul răspunde. Acest lucru împiedică continuarea codului cu date nedefinite. #### Pasul 4: Crearea unui spațiu pentru datele tale Aplicația ta are nevoie de un loc unde să păstreze informațiile contului odată ce sunt încărcate. Gândește-te la acest lucru ca la memoria pe termen scurt a aplicației tale - un loc pentru a păstra datele utilizatorului curent la îndemână. Adaugă această linie în partea de sus a fișierului `app.js`: ```javascript // This holds the current user's account data let account = null; ``` **De ce avem nevoie de acest lucru:** - Păstrează datele contului accesibile de oriunde în aplicația ta - Începerea cu `null` înseamnă "nimeni nu este autentificat încă" - Se actualizează când cineva se autentifică sau se înregistrează cu succes - Acționează ca o sursă unică de adevăr - fără confuzii despre cine este autentificat #### Pasul 5: Conectarea formularului tău Acum să conectăm noua ta funcție de autentificare la formularul HTML. Actualizează eticheta formularului astfel: ```html
``` **Ce face această mică modificare:** - Oprește formularul din comportamentul său implicit de "reîncărcare a întregii pagini" - Apelează funcția ta personalizată JavaScript în schimb - Păstrează totul fluid și în stilul aplicațiilor cu o singură pagină - Îți oferă control complet asupra a ceea ce se întâmplă când utilizatorii apasă "Autentificare" #### Pasul 6: Îmbunătățirea funcției de înregistrare Pentru consistență, actualizează funcția ta `register` pentru a stoca și datele contului și pentru a naviga la tabloul de bord: ```javascript // Add these lines at the end of your register function account = result; navigate('/dashboard'); ``` **Această îmbunătățire oferă:** - **Tranziție lină** de la înregistrare la tabloul de bord - **Experiență consistentă** pentru utilizator între fluxurile de autentificare și înregistrare - **Acces imediat** la datele contului după înregistrarea cu succes #### Testarea implementării tale ```mermaid flowchart TD A[User enters credentials] --> B[Login function called] B --> C[Fetch account data from server] C --> D{Data received successfully?} D -->|Yes| E[Store account data globally] D -->|No| F[Display error message] E --> G[Navigate to dashboard] F --> H[User stays on login page] ``` **Este timpul să testezi:** 1. Creează un cont nou pentru a te asigura că totul funcționează 2. Încearcă să te autentifici cu aceleași acreditări 3. Aruncă o privire în consola browserului tău (F12) dacă ceva pare în neregulă 4. Asigură-te că ajungi pe tabloul de bord după o autentificare reușită Dacă ceva nu funcționează, nu te panica! Majoritatea problemelor sunt ușor de rezolvat, cum ar fi greșelile de tastare sau uitarea de a porni serverul API. #### Un cuvânt rapid despre magia Cross-Origin Te-ai putea întreba: "Cum comunică aplicația mea web cu acest server API când rulează pe porturi diferite?" Întrebare excelentă! Acest lucru atinge un subiect pe care fiecare dezvoltator web îl întâlnește la un moment dat. > 🔒 **Securitatea Cross-Origin**: Browserele aplică o "politică de origine comună" pentru a preveni comunicarea neautorizată între domenii diferite. La fel ca sistemul de verificare la Pentagon, ele verifică dacă comunicarea este autorizată înainte de a permite transferul de date. > **În configurația noastră:** - Aplicația ta web rulează pe `localhost:3000` (server de dezvoltare) - Serverul API rulează pe `localhost:5000` (server backend) - Serverul API include anteturi [CORS](https://developer.mozilla.org/docs/Web/HTTP/CORS) care autorizează explicit comunicarea din aplicația ta web Această configurație reflectă dezvoltarea reală, unde aplicațiile frontend și backend rulează de obicei pe servere separate. > 📚 **Află mai multe**: Explorează mai profund API-urile și preluarea datelor cu acest modul cuprinzător [Microsoft Learn despre API-uri](https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=academic-77807-sagibbon). ## Adăugarea datelor în HTML Acum vom face ca datele preluate să fie vizibile utilizatorilor prin manipularea DOM. La fel ca procesul de dezvoltare a fotografiilor într-o cameră obscură, transformăm datele invizibile în ceva ce utilizatorii pot vedea și interacționa. Manipularea DOM este tehnica care transformă paginile web statice în aplicații dinamice care își actualizează conținutul pe baza interacțiunilor utilizatorilor și a răspunsurilor serverului. ### Alegerea instrumentului potrivit pentru sarcină Când vine vorba de actualizarea HTML-ului cu JavaScript, ai mai multe opțiuni. Gândește-te la acestea ca la diferite instrumente dintr-o trusă - fiecare perfect pentru sarcini specifice: | Metodă | Pentru ce este excelentă | Când să o folosești | Nivel de siguranță | |--------|--------------------------|---------------------|--------------------| | `textContent` | Afișarea datelor utilizatorului în siguranță | Oricând afișezi text | ✅ Foarte sigur | | `createElement()` + `append()` | Construirea layout-urilor complexe | Crearea de secțiuni/listări noi | ✅ Sigur | | `innerHTML` | Setarea conținutului HTML | ⚠️ Încearcă să eviți această metodă | ❌ Riscuri mari | #### Modul sigur de a afișa text: textContent Proprietatea [`textContent Pentru conținut mai complex, combină [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) cu metoda [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append): ```javascript // Safe way to create new elements const transactionItem = document.createElement('div'); transactionItem.className = 'transaction-item'; transactionItem.textContent = `${transaction.date}: ${transaction.description}`; container.append(transactionItem); ``` **Înțelegerea acestei abordări:** - **Creează** elemente DOM noi programatic - **Oferă** control complet asupra atributelor și conținutului elementelor - **Permite** structuri complexe, cu elemente imbricate - **Asigură** securitatea prin separarea structurii de conținut > ⚠️ **Considerație de securitate**: Deși [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) apare în multe tutoriale, poate executa scripturi încorporate. La fel ca protocoalele de securitate de la CERN care previn executarea codului neautorizat, utilizarea `textContent` și `createElement` oferă alternative mai sigure. > **Riscurile utilizării innerHTML:** - Execută orice taguri `