# Costruire un'app bancaria Parte 3: Metodi per recuperare e utilizzare i dati Pensa al computer dell'Enterprise in Star Trek: quando il Capitano Picard chiede lo stato della nave, le informazioni appaiono istantaneamente senza che l'interfaccia si blocchi o si ricostruisca completamente. Quel flusso continuo di informazioni è esattamente ciò che stiamo costruendo qui con il recupero dinamico dei dati. Al momento, la tua app bancaria è come un giornale stampato: informativa ma statica. La trasformeremo in qualcosa di simile al centro di controllo della NASA, dove i dati fluiscono continuamente e si aggiornano in tempo reale senza interrompere il flusso di lavoro dell'utente. Imparerai a comunicare con i server in modo asincrono, gestire i dati che arrivano in momenti diversi e trasformare informazioni grezze in qualcosa di significativo per i tuoi utenti. Questa è la differenza tra una demo e un software pronto per la produzione. ## Quiz Pre-Lettura [Quiz pre-lettura](https://ff-quizzes.netlify.app/web/quiz/45) ### Prerequisiti Prima di immergerti nel recupero dei dati, assicurati di avere questi componenti pronti: - **Lezione precedente**: Completa il [Modulo di Login e Registrazione](../2-forms/README.md) - costruiremo su questa base - **Server locale**: Installa [Node.js](https://nodejs.org) e [esegui l'API del server](../api/README.md) per fornire i dati dell'account - **Connessione API**: Testa la connessione al server con questo comando: ```bash curl http://localhost:5000/api # Expected response: "Bank API v1.0.0" ``` Questo rapido test garantisce che tutti i componenti comunichino correttamente: - Verifica che Node.js funzioni correttamente sul tuo sistema - Conferma che il server API sia attivo e risponda - Valida che la tua app possa raggiungere il server (come controllare il contatto radio prima di una missione) --- ## Comprendere il recupero dei dati nelle moderne app web Il modo in cui le applicazioni web gestiscono i dati è evoluto drasticamente negli ultimi due decenni. Comprendere questa evoluzione ti aiuterà ad apprezzare perché tecniche moderne come AJAX e l'API Fetch sono così potenti e perché sono diventate strumenti essenziali per gli sviluppatori web. Esploriamo come funzionavano i siti web tradizionali rispetto alle applicazioni dinamiche e reattive che costruiamo oggi. ### Applicazioni Multi-Pagina Tradizionali (MPA) Nei primi giorni del web, ogni clic era come cambiare canale su una vecchia televisione: lo schermo diventava nero, poi lentamente si sintonizzava sul nuovo contenuto. Questa era la realtà delle prime applicazioni web, dove ogni interazione significava ricostruire completamente l'intera pagina da 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) ```  **Perché questo approccio sembrava macchinoso:** - Ogni clic significava ricostruire l'intera pagina da zero - Gli utenti venivano interrotti nel bel mezzo dei loro pensieri da quei fastidiosi lampeggiamenti della pagina - La tua connessione internet lavorava il doppio scaricando ripetutamente la stessa intestazione e il piè di pagina - Le app sembravano più simili a un archivio di documenti che a un software ### Applicazioni Single-Page Moderne (SPA) AJAX (Asynchronous JavaScript and XML) ha completamente cambiato questo paradigma. Come il design modulare della Stazione Spaziale Internazionale, dove gli astronauti possono sostituire singoli componenti senza ricostruire l'intera struttura, AJAX ci consente di aggiornare parti specifiche di una pagina web senza ricaricare tutto. Nonostante il nome menzioni XML, oggi usiamo principalmente JSON, ma il principio di base rimane: aggiornare solo ciò che deve cambiare. ```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) ```  **Perché le SPA sono migliori:** - Vengono aggiornate solo le parti che effettivamente cambiano (intelligente, vero?) - Niente più interruzioni brusche: gli utenti rimangono concentrati - Meno dati viaggiano sulla rete, il che significa caricamenti più veloci - Tutto sembra fluido e reattivo, come le app sul tuo telefono ### L'evoluzione verso l'API Fetch moderna I browser moderni forniscono l'[`API Fetch`](https://developer.mozilla.org/docs/Web/API/Fetch_API), che sostituisce la vecchia [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Come la differenza tra usare un telegrafo e inviare un'email, l'API Fetch utilizza le promesse per un codice asincrono più pulito e gestisce naturalmente JSON. | Caratteristica | XMLHttpRequest | API Fetch | |----------------|----------------|-----------| | **Sintassi** | Complessa basata su callback | Pulita basata su promesse | | **Gestione JSON** | Richiede parsing manuale | Metodo `.json()` integrato | | **Gestione errori** | Informazioni limitate sugli errori | Dettagli completi sugli errori | | **Supporto moderno** | Compatibilità legacy | Promesse ES6+ e async/await | > 💡 **Compatibilità Browser**: Buone notizie: l'API Fetch funziona in tutti i browser moderni! Se sei curioso di conoscere versioni specifiche, [caniuse.com](https://caniuse.com/fetch) ha la storia completa sulla compatibilità. > **In sintesi:** - Funziona perfettamente su Chrome, Firefox, Safari e Edge (praticamente ovunque si trovino i tuoi utenti) - Solo Internet Explorer necessita di aiuto extra (e onestamente, è ora di lasciarlo andare) - Ti prepara perfettamente per i modelli eleganti async/await che useremo più avanti ### Implementare il Login Utente e il Recupero dei Dati Ora implementeremo il sistema di login che trasforma la tua app bancaria da una visualizzazione statica a un'applicazione funzionale. Come i protocolli di autenticazione utilizzati in strutture militari sicure, verificheremo le credenziali dell'utente e poi forniremo accesso ai loro dati specifici. Costruiremo questo gradualmente, partendo dall'autenticazione di base e poi aggiungendo le capacità di recupero dei dati. #### Passo 1: Creare la base della funzione di Login Apri il file `app.js` e aggiungi una nuova funzione `login`. Questa gestirà il processo di autenticazione dell'utente: ```javascript async function login() { const loginForm = document.getElementById('loginForm'); const user = loginForm.user.value; } ``` **Analizziamo questo codice:** - La parola chiave `async`? Sta dicendo a JavaScript "ehi, questa funzione potrebbe dover aspettare qualcosa" - Stiamo recuperando il nostro modulo dalla pagina (niente di complicato, lo troviamo semplicemente tramite il suo ID) - Poi estraiamo ciò che l'utente ha digitato come nome utente - Ecco un trucco interessante: puoi accedere a qualsiasi input del modulo tramite il suo attributo `name` - niente bisogno di chiamate extra a getElementById! > 💡 **Pattern di Accesso ai Moduli**: Ogni controllo del modulo può essere accessibile tramite il suo nome (impostato nell'HTML usando l'attributo `name`) come proprietà dell'elemento modulo. Questo fornisce un modo pulito e leggibile per ottenere i dati del modulo. #### Passo 2: Creare la funzione di recupero dei dati dell'account Successivamente, creeremo una funzione dedicata per recuperare i dati dell'account dal server. Questo segue lo stesso schema della funzione di registrazione ma si concentra sul recupero dei dati: ```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' }; } } ``` **Cosa fa questo codice:** - **Utilizza** l'API `fetch` moderna per richiedere dati in modo asincrono - **Costruisce** un URL di richiesta GET con il parametro del nome utente - **Applica** `encodeURIComponent()` per gestire in modo sicuro i caratteri speciali negli URL - **Converte** la risposta in formato JSON per una facile manipolazione dei dati - **Gestisce** gli errori in modo elegante restituendo un oggetto di errore invece di bloccarsi > ⚠️ **Nota di Sicurezza**: La funzione `encodeURIComponent()` gestisce i caratteri speciali negli URL. Come i sistemi di codifica utilizzati nelle comunicazioni navali, garantisce che il tuo messaggio arrivi esattamente come previsto, impedendo che caratteri come "#" o "&" vengano interpretati erroneamente. > **Perché è importante:** - Impedisce ai caratteri speciali di rompere gli URL - Protegge da attacchi di manipolazione degli URL - Garantisce che il server riceva i dati previsti - Segue pratiche di codifica sicure #### Comprendere le richieste HTTP GET Ecco qualcosa che potrebbe sorprenderti: quando usi `fetch` senza opzioni extra, crea automaticamente una richiesta [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET). Questo è perfetto per ciò che stiamo facendo: chiedere al server "ehi, posso vedere i dati dell'account di questo utente?" Pensa alle richieste GET come chiedere gentilmente di prendere in prestito un libro dalla biblioteca: stai chiedendo di vedere qualcosa che già esiste. Le richieste POST (che abbiamo usato per la registrazione) sono più simili a inviare un nuovo libro da aggiungere alla collezione. | Richiesta GET | Richiesta POST | |---------------|---------------| | **Scopo** | Recuperare dati esistenti | Inviare nuovi dati al server | | **Parametri** | Nel percorso/query string dell'URL | Nel corpo della richiesta | | **Caching** | Può essere memorizzata dai browser | Non tipicamente memorizzata | | **Sicurezza** | Visibile nell'URL/log | Nascosta nel corpo della richiesta | #### Passo 3: Unire tutto insieme Ora arriva la parte soddisfacente: colleghiamo la funzione di recupero dei dati dell'account al processo di login. Questo è il momento in cui tutto si incastra: ```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'); } ``` Questa funzione segue una sequenza chiara: - Estrae il nome utente dall'input del modulo - Richiede i dati dell'account dell'utente al server - Gestisce eventuali errori che si verificano durante il processo - Memorizza i dati dell'account e naviga al dashboard in caso di successo > 🎯 **Pattern Async/Await**: Poiché `getAccount` è una funzione asincrona, utilizziamo la parola chiave `await` per sospendere l'esecuzione fino a quando il server non risponde. Questo impedisce al codice di continuare con dati non definiti. #### Passo 4: Creare una memoria per i tuoi dati La tua app ha bisogno di un posto dove ricordare le informazioni dell'account una volta caricate. Pensa a questo come alla memoria a breve termine della tua app: un luogo per tenere i dati dell'utente corrente a portata di mano. Aggiungi questa riga all'inizio del tuo file `app.js`: ```javascript // This holds the current user's account data let account = null; ``` **Perché ne abbiamo bisogno:** - Mantiene i dati dell'account accessibili da qualsiasi parte della tua app - Iniziare con `null` significa "nessuno è ancora loggato" - Viene aggiornato quando qualcuno effettua il login o la registrazione con successo - Funziona come una fonte unica di verità - nessuna confusione su chi è loggato #### Passo 5: Collegare il modulo Ora colleghiamo la tua nuova funzione di login al modulo HTML. Aggiorna il tag del modulo in questo modo: ```html
``` **Cosa fa questa piccola modifica:** - Impedisce al modulo di eseguire il comportamento predefinito "ricarica l'intera pagina" - Chiama la tua funzione JavaScript personalizzata - Mantiene tutto fluido e simile a un'app single-page - Ti dà il controllo completo su ciò che accade quando gli utenti cliccano su "Login" #### Passo 6: Migliorare la funzione di registrazione Per coerenza, aggiorna la tua funzione `register` per memorizzare anche i dati dell'account e navigare al dashboard: ```javascript // Add these lines at the end of your register function account = result; navigate('/dashboard'); ``` **Questo miglioramento offre:** - **Transizione fluida** dalla registrazione al dashboard - **Esperienza utente coerente** tra i flussi di login e registrazione - **Accesso immediato** ai dati dell'account dopo una registrazione riuscita #### Testare la tua implementazione ```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] ``` **È ora di metterlo alla prova:** 1. Crea un nuovo account per assicurarti che tutto funzioni 2. Prova a effettuare il login con le stesse credenziali 3. Dai un'occhiata alla console del tuo browser (F12) se qualcosa sembra non funzionare 4. Assicurati di arrivare al dashboard dopo un login riuscito Se qualcosa non funziona, non farti prendere dal panico! La maggior parte dei problemi sono semplici da risolvere, come errori di battitura o dimenticare di avviare il server API. #### Una parola veloce sulla magia Cross-Origin Potresti chiederti: "Come fa la mia app web a comunicare con questo server API se funzionano su porte diverse?" Ottima domanda! Questo tocca qualcosa che ogni sviluppatore web incontra prima o poi. > 🔒 **Sicurezza Cross-Origin**: I browser applicano una "same-origin policy" per impedire comunicazioni non autorizzate tra domini diversi. Come il sistema di controllo degli accessi al Pentagono, verificano che la comunicazione sia autorizzata prima di consentire il trasferimento dei dati. > **Nel nostro setup:** - La tua app web funziona su `localhost:3000` (server di sviluppo) - Il tuo server API funziona su `localhost:5000` (server backend) - Il server API include intestazioni [CORS](https://developer.mozilla.org/docs/Web/HTTP/CORS) che autorizzano esplicitamente la comunicazione dalla tua app web Questa configurazione rispecchia lo sviluppo nel mondo reale, dove le applicazioni frontend e backend funzionano tipicamente su server separati. > 📚 **Per saperne di più**: Approfondisci gli API e il recupero dei dati con questo modulo completo di [Microsoft Learn sugli API](https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=academic-77807-sagibbon). ## Dare vita ai tuoi dati in HTML Ora renderemo i dati recuperati visibili agli utenti attraverso la manipolazione del DOM. Come il processo di sviluppo delle fotografie in una camera oscura, trasformeremo i dati invisibili in qualcosa che gli utenti possono vedere e con cui possono interagire. La manipolazione del DOM è la tecnica che trasforma le pagine web statiche in applicazioni dinamiche che aggiornano il loro contenuto in base alle interazioni degli utenti e alle risposte del server. ### Scegliere lo strumento giusto per il lavoro Quando si tratta di aggiornare il tuo HTML con JavaScript, hai diverse opzioni. Pensa a queste come a diversi strumenti in una cassetta degli attrezzi: ognuno perfetto per lavori specifici. | Metodo | Per cosa è ottimo | Quando usarlo | Livello di sicurezza | |--------|-------------------|---------------|-----------------------| | `textContent` | Mostrare dati utente in modo sicuro | Ogni volta che mostri testo | ✅ Molto sicuro | | `createElement()` + `append()` | Creare layout complessi | Creare nuove sezioni/liste | ✅ Molto sicuro | | `innerHTML` | Impostare contenuti HTML | ⚠️ Cerca di evitarlo | ❌ Rischioso | #### Il modo sicuro per mostrare il testo: textContent La proprietà [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent) è la tua migliore amica quando si tratta di mostrare i dati degli utenti. È come avere un buttafuori per la tua pagina web: niente di dannoso passa: ```javascript // The safe, reliable way to update text const balanceElement = document.getElementById('balance'); balanceElement.textContent = account.balance; ``` **Vantaggi di textContent:** - Tratta tutto come testo semplice (impedisce l'esecuzione di script) - Cancella automaticamente il contenuto esistente - Efficiente per aggiornamenti di testo semplici - Fornisce sicurezza integrata contro contenuti dannosi #### Creare elementi HTML dinamici Per contenuti più complessi, combina [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) con il metodo [`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); ``` **Comprendere questo approccio:** - **Crea** nuovi elementi DOM in modo programmatico - **Mantiene** il pieno controllo sugli attributi e sui contenuti degli elementi - **Consente** strutture di elementi complesse e nidificate - **Preserva** la sicurezza separando la struttura dal contenuto > ⚠️ **Considerazione sulla sicurezza**: Sebbene [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) appaia in molti tutorial, può eseguire script incorporati. Come i protocolli di sicurezza al CERN che impediscono l'esecuzione di codice non autorizzato, l'uso di `textContent` e `createElement` offre alternative più sicure. > **Rischi di innerHTML:** - Esegue qualsiasi tag `