Skip to content

Latest commit

 

History

History
799 lines (591 loc) · 39 KB

File metadata and controls

799 lines (591 loc) · 39 KB

Construiește o Aplicație Bancară Partea 4: Concepte de Gestionare a Stării

⚡ Ce Poți Face în Următoarele 5 Minute

Cale rapidă de început pentru dezvoltatori ocupați

flowchart LR
    A[⚡ 5 minute] --> B[Diagnosticare probleme de stare]
    B --> C[Creează obiect central de stare]
    C --> D[Adaugă funcția updateState]
    D --> E[Vezi îmbunătățiri imediate]
Loading
  • Minutul 1: Testează problema actuală cu starea - autentifică-te, reîmprospătează pagina, observă deconectarea
  • Minutul 2: Înlocuiește let account = null cu let state = { account: null }
  • Minutul 3: Creează o funcție simplă updateState() pentru actualizări controlate
  • Minutul 4: Actualizează o funcție să folosească noul model
  • Minutul 5: Testează predictibilitatea și capacitatea de depanare îmbunătățite

Test de diagnostic rapid:

// Înainte: Stare dispersată
let account = null; // Pierdut la reîmprospătare!

// După: Stare centralizată
let state = Object.freeze({ account: null }); // Controlată și urmăribilă!

De ce contează asta: În 5 minute, vei experimenta transformarea de la o gestionare haotică a stării la modele predictibile și ușor de depanat. Aceasta este fundația care face aplicațiile complexe ușor de întreținut.

🗺️ Călătoria ta de învățare prin măiestria gestionării stării

journey
    title De la Stare Împrăștiată la Arhitectură Profesională
    section Diagnosticarea Problemelor
      Identifică problemele de pierdere a stării: 3: You
      Înțelege actualizările împrăștiate: 4: You
      Recunoaște nevoile arhitecturale: 6: You
    section Centralizarea Controlului
      Creează un obiect de stare unificat: 5: You
      Implementează actualizări controlate: 7: You
      Adaugă modele imuabile: 8: You
    section Adăugarea Persistenței
      Implementează localStorage: 6: You
      Gestionează serializarea: 7: You
      Creează continuitatea sesiunii: 9: You
    section Echilibrarea Prospețimii
      Abordează învechirea datelor: 5: You
      Construiește sisteme de reîmprospătare: 8: You
      Obține echilibrul optim: 9: You
Loading

Destinația călătoriei tale: Până la finalul acestei lecții, vei fi construit un sistem profesional de gestionare a stării care se ocupă de persistență, actualitatea datelor și actualizări previzibile - aceleași modele folosite în aplicațiile de producție.

Quiz Pre-Lecție

Quiz pre-lectură

Introducere

Gestionarea stării este ca sistemul de navigație de pe nava Voyager – când totul funcționează bine, abia o observi. Dar când ceva nu merge, devine diferența între a ajunge în spațiul interstelar și a pluti pierdut în vidul cosmic. În dezvoltarea web, starea reprezintă tot ceea ce aplicația ta trebuie să-și amintească: statusul autentificării utilizatorului, datele din formulare, istoricul navigării și stările temporare ale interfeței.

Pe măsură ce aplicația ta bancară a evoluat de la un formular simplu de autentificare la o aplicație mai sofisticată, probabil ai întâmpinat câteva provocări comune. Reîmprospătează pagina și utilizatorii sunt deconectați neașteptat. Închide browserul și tot progresul dispare. Depanezi o problemă și cauți prin mai multe funcții care toate modifică aceleași date în moduri diferite.

Acestea nu sunt semne de cod prost – sunt durerile naturale de creștere care apar când aplicațiile ating un anumit nivel de complexitate. Fiecare dezvoltator se confruntă cu aceste provocări pe măsură ce aplicațiile lor trec de la „prototip” la „pregătit pentru producție”.

În această lecție, vom implementa un sistem centralizat de gestionare a stării care transformă aplicația ta bancară într-una fiabilă, profesională. Vei învăța să gestionezi fluxurile de date în mod predictibil, să persiști sesiunile utilizatorilor corespunzător și să creezi o experiență lină pentru utilizator, așa cum cer aplicațiile moderne web.

Precondiții

Înainte să te adâncești în conceptele gestionării stării, trebuie să ai mediul de dezvoltare configurat corect și fundamentul aplicației bancare în loc. Această lecție se bazează direct pe conceptele și codul din părțile anterioare ale acestui serial.

Asigură-te că ai următoarele componente pregătite înainte de a continua:

Configurare necesară:

  • Finalizează lecția despre extragerea datelor - aplicația ta trebuie să încarce și să afișeze cu succes datele contului
  • Instalează Node.js pe sistemul tău pentru a rula backend-ul API
  • Pornește serverul API local pentru a gestiona operațiunile cu datele contului

Testarea mediului tău:

Verifică dacă serverul API este funcțional executând această comandă într-un terminal:

curl http://localhost:5000/api
# -> ar trebui să returneze "Bank API v1.0.0" ca rezultat

Ce face această comandă:

  • Trimite o cerere GET către serverul tău API local
  • Testează conexiunea și verifică dacă serverul răspunde
  • Returnează informații despre versiunea API dacă totul funcționează corect

🧠 Prezentare generală a arhitecturii gestiunii stării

mindmap
  root((Gestionarea Stării))
    Probleme Curente
      Pierderea Sesiunii
        Probleme cu Reîmprospătarea Paginii
        Impactul Închiderii Browser-ului
        Probleme cu Resetarea Variabilelor
      Actualizări Împrăștiate
        Puncte Multiple de Modificare
        Provocări la Debugging
        Comportament Imprevizibil
      Curățare Incompletă
        Probleme cu Starea de Deconectare
        Scurgeri de Memorie
        Îngrijorări privind Securitatea
    Soluții Centralizate
      Obiectul Unificat al Stării
        Sursa Unică de Adevăr
        Structură Predictibilă
        Fundație Scalabilă
      Actualizări Controlate
        Modele Imutabile
        Utilizarea Object.freeze
        Modificări Bazate pe Funcții
      Urmărirea Stării
        Gestionarea Istoricului
        Vizibilitate la Debug
        Auditarea Modificărilor
    Strategii de Persistență
      Integrare localStorage
        Continuitatea Sesiunii
        Serializare JSON
        Sincronizare Automată
      Prospetimea Datelor
        Reîmprospătare de la Server
        Gestionarea Datelor Învechite
        Optimizarea Echilibrului
      Optimizarea Stocării
        Date Minimale
        Focalizare pe Performanță
        Considerații de Securitate
Loading

Principiul de bază: Gestionarea profesională a stării echilibrează predictibilitatea, persistența și performanța pentru a crea experiențe fiabile pentru utilizatori care pot scala de la interacțiuni simple la fluxuri complexe de lucru ale aplicațiilor.


Diagnosticarea problemelor actuale cu starea

Ca Sherlock Holmes examinând o scenă de crimă, trebuie să înțelegem exact ce se întâmplă în implementarea noastră actuală înainte să putem rezolva misterul sesiunilor utilizatorilor care dispar.

Să facem un experiment simplu care dezvăluie provocările fundamentale ale gestionării stării:

🧪 Încearcă acest test de diagnostic:

  1. Autentifică-te în aplicația bancară și navighează către tabloul de bord
  2. Reîmprospătează pagina browserului
  3. Observă ce se întâmplă cu statusul tău de autentificare

Dacă ești redirecționat înapoi la ecranul de autentificare, ai descoperit problema clasică a persistenței stării. Acest comportament apare deoarece implementarea noastră actuală stochează datele utilizatorului în variabile JavaScript care se resetează la fiecare încărcare de pagină.

Problemele implementării curente:

Variabila simplă account din lecția noastră anterioră creează trei probleme semnificative, care afectează atât experiența utilizatorului cât și mentenabilitatea codului:

Problemă Cauză Tehnică Impact asupra Utilizatorului
Pierderea sesiunii Reîmprospătarea paginii șterge variabilele JavaScript Utilizatorii trebuie să se autentifice frecvent
Actualizări împrăștiate Mai multe funcții modifică starea direct Debuggingul devine din ce în ce mai dificil
Curățare incompletă Deconectarea nu șterge toate referințele din stare Riscuri potențiale de securitate și confidențialitate

Provocarea arhitecturală:

Ca designul compartimentalizat al Titanicului care părea robust până când mai multe compartimente s-au inundat simultan, rezolvarea acestor probleme individual nu va aborda problema arhitecturală de bază. Avem nevoie de o soluție cuprinzătoare de gestionare a stării.

💡 Ce încercăm cu adevărat să realizăm aici?

Gestionarea stării este de fapt rezolvarea a două enigme fundamentale:

  1. Unde sunt datele mele?: Urmărirea ce informații avem și de unde provin
  2. Sunt toți pe aceeași pagină?: Asigurarea că utilizatorii văd ceea ce se întâmplă cu adevărat

Planul nostru de acțiune:

În loc să ne învârtim în cerc, vom crea un sistem centralizat de gestionare a stării. Gândește-te la asta ca la o persoană foarte organizată care răspunde de toate lucrurile importante:

Schema care arată fluxurile de date între HTML, acțiunile utilizatorului și stare

flowchart TD
    A[Acțiune Utilizator] --> B[Gestionar Eveniment]
    B --> C[Funcția updateState]
    C --> D{Validarea Stării}
    D -->|Valid| E[Creează Stare Nouă]
    D -->|Invalid| F[Gestionare Eroare]
    E --> G[Object.freeze]
    G --> H[Actualizează localStorage]
    H --> I[Declanșează Actualizare UI]
    I --> J[Utilizatorul Vede Schimbările]
    F --> K[Utilizatorul Vede Eroarea]
    
    subgraph "Stratul de Gestionare a Stării"
        C
        E
        G
    end
    
    subgraph "Stratul de Persistență"
        H
        L[localStorage]
        H -.-> L
    end
Loading

Înțelegerea acestui flux de date:

  • Centralizează toată starea aplicației într-un singur loc
  • Dirijează toate schimbările de stare prin funcții controlate
  • Asigură că UI rămâne sincronizat cu starea curentă
  • Oferă un tipar clar și predictibil pentru gestionarea datelor

💡 Insight profesional: Această lecție este concentrată pe conceptele fundamentale. Pentru aplicații complexe, biblioteci precum Redux oferă funcții de gestionare a stării mai avansate. Înțelegerea acestor principii de bază te va ajuta să stăpânești orice bibliotecă de gestionare a stării.

⚠️ Subiect avansat: Nu vom acoperi actualizările automate ale UI cauzate de schimbările în stare, deoarece implică concepte de Programare Reactivă. Consideră asta următorul pas excelent în călătoria ta de învățare!

Sarcina: Centralizarea Structurii Stării

Să începem transformarea gestionării noastre dispersate a stării într-un sistem centralizat. Acest prim pas stabilește baza pentru toate îmbunătățirile care urmează.

Pasul 1: Creează un obiect central de stare

Înlocuiește declarația simplă account:

let account = null;

Cu un obiect structurat de stare:

let state = {
  account: null
};

De ce contează această schimbare:

  • Centralizează toate datele aplicației într-un singur loc
  • Pregătește structura pentru adăugarea mai multor proprietăți ale stării ulterior
  • Creează o graniță clară între stare și alte variabile
  • Stabilește un model care poate scala pe măsură ce aplicația ta crește

Pasul 2: Actualizează modelele de acces la stare

Actualizează funcțiile pentru a folosi noua structură de stare:

În funcțiile register() și login(), înlocuiește:

account = ...

Cu:

state.account = ...

În funcția updateDashboard(), adaugă această linie în partea de sus:

const account = state.account;

Ce realizează aceste actualizări:

  • Menține funcționalitatea existentă, în timp ce îmbunătățește structura
  • Pregătește codul pentru o gestiune a stării mai sofisticată
  • Creează modele consistente pentru accesarea datelor din stare
  • Stabilește fundația pentru actualizări centralizate ale stării

💡 Notă: Această refactorizare nu rezolvă imediat problemele, dar creează fundația esențială pentru îmbunătățirile puternice ce vor urma!

🎯 Verificare pedagogică: Principiile centralizării

Pauză și reflecție: Tocmai ai implementat baza gestionării centralizate a stării. Aceasta este o decizie arhitecturală crucială.

Autoevaluare rapidă:

  • Poți explica de ce centralizarea stării într-un singur obiect este mai bună decât variabilele împrăștiate?
  • Ce s-ar întâmpla dacă ai uita să actualizezi o funcție să folosească state.account?
  • Cum pregătește acest model codul pentru funcționalități mai avansate?

Conexiune cu lumea reală: Pattern-ul de centralizare învățat este fundația framework-urilor moderne ca Redux, Vuex și React Context. Construiești aceeași gândire arhitecturală folosită în aplicațiile majore.

Întrebare provocatoare: Dacă ar trebui să adaugi preferințe ale utilizatorului (temă, limbă) în aplicația ta, unde le-ai adăuga în structura stării? Cum ar escala acesta?

Implementarea Actualizărilor Controlate ale Stării

Odată ce starea noastră este centralizată, următorul pas este să stabilim mecanisme controlate pentru modificarea datelor. Această abordare asigură schimbări de stare previzibile și depanare mai ușoară.

Principiul de bază seamănă cu controlul traficului aerian: în loc să permitem ca mai multe funcții să modifice starea independent, vom canaliza toate schimbările printr-o singură funcție controlată. Acest model oferă o supraveghere clară a momentului și modului în care apar modificările.

Gestionarea stării imutabile:

Vom trata obiectul nostru state ca pe unul imutabil, adică nu-l modificăm direct niciodată. În schimb, fiecare schimbare creează un nou obiect de stare cu datele actualizate.

Deși această abordare poate părea inițial ineficientă comparativ cu modificările directe, oferă avantaje semnificative pentru depanare, testare și menținerea predictibilității aplicației.

Beneficiile gestionării imuabile a stării:

Beneficiu Descriere Impact
Predictibilitate Schimbările apar doar prin funcții controlate Mai ușor de depanat și testat
Urmărirea istoricului Fiecare schimbare creează un obiect nou Permite funcționalități undo/redo
Prevenirea efectelor secundare Nici o modificare accidentală Previne erori misterioase
Optimizarea performanței Ușor de detectat când starea s-a schimbat realmente Permite actualizări eficiente ale UI

Imutabilitatea în JavaScript cu Object.freeze():

JavaScript oferă Object.freeze() pentru a preveni modificările obiectelor:

const immutableState = Object.freeze({ account: userData });
// Orice încercare de a modifica immutableState va genera o eroare

Ce se întâmplă aici:

  • Previne atribuiri sau ștergeri directe de proprietăți
  • Aruncă excepții dacă se încearcă modificări
  • Asigură că schimbările stării trebuie să treacă prin funcții controlate
  • Creează un contract clar despre cum poate fi actualizată starea

💡 Explorați în profunzime: Află diferența dintre obiectele imuabile superficial și cele profund în documentația MDN. Înțelegerea acestei distincții este crucială pentru structuri complexe de stare.

stateDiagram-v2
    [*] --> StateV1: Stare Inițială
    StateV1 --> StateV2: updateState('account', newData)
    StateV2 --> StateV3: updateState('account', anotherUpdate)
    StateV3 --> StateV4: updateState('preferences', userSettings)
    
    note right of StateV1
        Object.freeze()
        Imuabil
        Ușor de depanat
    end note
    
    note right of StateV2
        Obiect nou creat
        Starea anterioară păstrată
        Schimbări previzibile
    end note
Loading

Sarcina

Să creăm o nouă funcție updateState():

function updateState(property, newData) {
  state = Object.freeze({
    ...state,
    [property]: newData
  });
}

În această funcție, creăm un nou obiect de stare și copiem datele din starea precedentă folosind operatorul spread (...). Apoi suprascriem o proprietate anume a obiectului de stare cu noile date folosind notația cu paranteze pătrate [property] pentru atribuire. În final, blocăm obiectul pentru a preveni modificările folosind Object.freeze(). Deocamdată în stare avem doar proprietatea account, dar cu această abordare poți adăuga câte proprietăți dorești.

De asemenea, vom actualiza inițializarea stării pentru a ne asigura că starea inițială este și ea blocată:

let state = Object.freeze({
  account: null
});

După aceea, actualizează funcția register înlocuind atribuirile state.account = result; cu:

updateState('account', result);

Fă același lucru cu funcția login, înlocuind state.account = data; cu:

updateState('account', data);

Acum vom profita de ocazie pentru a rezolva problema faptului că datele contului nu se șterg când utilizatorul face clic pe Logout.

Creează o nouă funcție logout():

function logout() {
  updateState('account', null);
  navigate('/login');
}

În updateDashboard(), înlocuiește redirecționarea return navigate('/login'); cu return logout();

Încearcă să înregistrezi un cont nou, să te deconectezi și să te autentifici din nou pentru a verifica că totul funcționează corect.

Sfat: poți vedea toate schimbările de stare adăugând console.log(state) la finalul funcției updateState() și deschizând consola în uneltelor de dezvoltare ale browserului.

Implementarea persistentei datelor

Problema pierderii sesiunii pe care am identificat-o anterior necesită o soluție de persistență care menține starea utilizatorului între sesiunile browserului. Aceasta transformă aplicația noastră dintr-o experiență temporară într-un instrument fiabil și profesional.

Gândește-te cum ceasurile atomice mențin timpul precis chiar și în timpul unor pene de curent prin stocarea stării critice în memorie non-volatile. În mod similar, aplicațiile web au nevoie de mecanisme de stocare persistentă pentru a păstra datele esențiale ale utilizatorului între sesiunile browserului și reîmprospătări de pagină.

Întrebări strategice pentru persistența datelor:

Înainte de a implementa persistența, ia în considerare acești factori critici:

Întrebare Contextul aplicației bancare Impactul deciziei
Datele sunt sensibile? Sold cont, istoricul tranzacțiilor Alege metode sigure de stocare
Cât timp ar trebui să persiste? Starea de autentificare vs. preferințe UI temporare Selectați durata de stocare potrivită
Serverul are nevoie de asta? Token-uri de autentificare vs. setări UI Determinați cerințele de partajare

Opțiuni de stocare în browser:

Browserele moderne oferă mai multe mecanisme de stocare, fiecare conceput pentru cazuri de utilizare diferite:

API-uri principale de stocare:

  1. localStorage: Stocare persistentă cheie/valoare

    • Persistă datele între sesiunile browserului pe termen nelimitat
    • Supraviețuiește repornirilor browserului și calculatorului
    • Este limitat la domeniul specific al site-ului web
    • Perfect pentru preferințele utilizatorilor și stările de autentificare
  2. sessionStorage: Stocare temporară în sesiune

    • Funcționează identic cu localStorage în timpul sesiunilor active
    • Se golește automat când se închide fila browserului
    • Ideal pentru date temporare care nu trebuie să persiste
  3. Cookie-uri HTTP: Stocare partajată pe server

    • Sunt trimise automat cu fiecare cerere către server
    • Perfecte pentru token-uri de autentificare
    • Au dimensiuni limitate și pot afecta performanța

Cerere de serializare a datelor:

Atât localStorage, cât și sessionStorage stochează numai șiruri de caractere:

// Conversia obiectelor în șiruri JSON pentru stocare
const accountData = { user: 'john', balance: 150 };
localStorage.setItem('account', JSON.stringify(accountData));

// Analizează șirurile JSON înapoi în obiecte la preluare
const savedAccount = JSON.parse(localStorage.getItem('account'));

Înțelegerea serializării:

  • Convertește obiectele JavaScript în șiruri JSON folosind JSON.stringify()
  • Reconstruiește obiectele din JSON folosind JSON.parse()
  • Gestionează automat obiecte și array-uri complexe și imbricate
  • Eșuează pentru funcții, valori nedefinite și referințe circulare

💡 Opțiune avansată: Pentru aplicații offline complexe cu seturi mari de date, luați în considerare API-ul IndexedDB. Acesta oferă o bază de date completă pe client, dar necesită o implementare mai complexă.

quadrantChart
    title Opțiuni de Stocare în Browser
    x-axis Complexitate Scăzută --> Complexitate Ridicată
    y-axis Durată Scurtă --> Durată Lungă
    
    quadrant-1 Unelte Profesionale
    quadrant-2 Persistență Simplă
    quadrant-3 Stocare Temporară
    quadrant-4 Sisteme Avansate
    
    localStorage: [0.3, 0.8]
    sessionStorage: [0.2, 0.2]
    HTTP Cookies: [0.6, 0.7]
    IndexedDB: [0.9, 0.9]
    Memory Variables: [0.1, 0.1]
Loading

Sarcină: Implementați persistența localStorage

Să implementăm stocarea persistentă astfel încât utilizatorii să rămână conectați până se deconectează explicit. Vom folosi localStorage pentru a stoca datele contului pe parcursul sesiunilor browserului.

Pasul 1: Definiți configurația de stocare

const storageKey = 'savedAccount';

Ce oferă această constantă:

  • Creează un identificator consistent pentru datele stocate
  • Previne greșelile de scriere în referințele la cheia de stocare
  • Facilitează modificarea cheii de stocare la nevoie
  • Urmărește cele mai bune practici pentru cod ușor de întreținut

Pasul 2: Adăugați persistența automată

Adăugați această linie la finalul funcției updateState():

localStorage.setItem(storageKey, JSON.stringify(state.account));

Ce se întâmplă aici:

  • Convertește obiectul contului într-un șir JSON pentru stocare
  • Salvează datele folosind cheia noastră consistentă de stocare
  • Se execută automat de fiecare dată când apar modificări de stare
  • Asigură că datele stocate sunt întotdeauna sincronizate cu starea curentă

💡 Beneficiu arhitectural: Deoarece am centralizat toate actualizările de stare prin updateState(), adăugarea persistenței a necesitat doar o linie de cod. Acesta este un exemplu al puterii deciziilor arhitecturale bune!

Pasul 3: Restaurarea stării la încărcarea aplicației

Creați o funcție de inițializare pentru a restaura datele salvate:

function init() {
  const savedAccount = localStorage.getItem(storageKey);
  if (savedAccount) {
    updateState('account', JSON.parse(savedAccount));
  }

  // Codul nostru anterior de inițializare
  window.onpopstate = () => updateRoute();
  updateRoute();
}

init();

Înțelegerea procesului de inițializare:

  • Recuperează orice date salvate anterior despre cont din localStorage
  • Parsează șirul JSON înapoi într-un obiect JavaScript
  • Actualizează starea folosind funcția noastră de actualizare controlată
  • Restaurează automat sesiunea utilizatorului la încărcarea paginii
  • Se execută înainte de actualizările rutei pentru a asigura disponibilitatea stării

Pasul 4: Optimizarea rutei implicite

Actualizați ruta implicită pentru a profita de persistență:

În updateRoute(), înlocuiți:

// Înlocuiește: return navigate('/login');
return navigate('/dashboard');

De ce acest schimb este potrivit:

  • Valorifică noul nostru sistem de persistență eficient
  • Permite panoului de control să gestioneze verificările de autentificare
  • Redirecționează automat către autentificare dacă nu există sesiune salvată
  • Creează o experiență utilizator mai fluidă

Testarea implementării:

  1. Autentificați-vă în aplicația bancară
  2. Reîncărcați pagina browserului
  3. Verificați că rămâneți autentificat și pe dashboard
  4. Închideți și redeschideți browserul
  5. Navigați înapoi la aplicație și confirmați că sunteți încă autentificat

🎉 Realizare de succes: Ați implementat cu succes managementul stării persistente! Aplicația dvs. se comportă acum ca o aplicație web profesională.

🎯 Verificare pedagogică: Arhitectura persistenței

Înțelegerea arhitecturii: Ați implementat un strat sofisticat de persistență care echilibrează experiența utilizatorului cu complexitatea gestionării datelor.

Concepte-cheie stăpânite:

  • Serializare JSON: conversia obiectelor complexe în șiruri stocabile
  • Sincronizare automată: modificările stării declanșează salvarea persistentă
  • Recuperarea sesiunii: aplicațiile pot restaura contextul utilizatorului după întreruperi
  • Persistență centralizată: o singură funcție de actualizare se ocupă de toată stocarea

Legătura cu industrie: Acest pattern de persistență este fundamental pentru Progressive Web Apps (PWA), aplicații offline-first și experiențe web mobile moderne. Construirea capabilităților la nivel de producție este asigurată.

Întrebare de reflecție: Cum ați modifica acest sistem pentru a gestiona mai multe conturi de utilizatori pe același dispozitiv? Luați în considerare implicațiile pentru confidențialitate și securitate.

Echilibrarea persistenței cu prospețimea datelor

Sistemul nostru de persistență menține cu succes sesiunile utilizatorilor, dar introduce o nouă provocare: învechirea datelor. Când mai mulți utilizatori sau aplicații modifică aceleași date pe server, informațiile memorate în cache local devin depășite.

Această situație este asemănătoare cu navigatorii vikingi care se bazau atât pe hărți stelare memorate, cât și pe observații cerești actuale. Hărțile ofereau consistență, dar navigatorii aveau nevoie de observații proaspete pentru a ține cont de condițiile schimbătoare. Similar, aplicația noastră are nevoie atât de starea utilizatorului persistentă, cât și de date server actualizate.

🧪 Descoperirea problemei învechirii datelor:

  1. Autentificați-vă în dashboard cu contul test
  2. Rulați această comandă în terminal pentru a simula o tranzacție dintr-o altă sursă:
curl --request POST \
     --header "Content-Type: application/json" \
     --data "{ \"date\": \"2020-07-24\", \"object\": \"Bought book\", \"amount\": -20 }" \
     http://localhost:5000/api/accounts/test/transactions
  1. Reîncărcați pagina dashboard în browser
  2. Observați dacă vedeți tranzacția nouă

Ce demonstrează acest test:

  • Arată cum stocarea locală poate deveni „învechită” (depășită)
  • Simulează scenarii reale unde datele se schimbă în afara aplicației
  • Relevă tensiunea dintre persistență și prospețimea datelor

Provocarea datelor învechite:

Problemă Cauză Impact asupra utilizatorului
Date învechite localStorage nu expiră automat Utilizatorii văd informații depășite
Modificări pe server Alte aplicații/utilizatori modifică aceleași date Vizualizări inconsistente pe platforme
Cache vs. realitate Cache-ul local nu corespunde stării serverului Experiență proastă și confuzie pentru utilizatori

Strategie de soluție:

Vom implementa un pattern „refresh la încărcare” care echilibrează beneficiile persistenței cu nevoia de date proaspete. Această abordare menține experiența fluidă a utilizatorului, asigurând în același timp acuratețea datelor.

sequenceDiagram
    participant U as Utilizator
    participant A as Aplicație
    participant L as localStorage
    participant S as Server
    
    U->>A: Deschide aplicația
    A->>L: Încarcă starea salvată
    L-->>A: Returnează datele cache
    A->>U: Afișează interfața imediat
    A->>S: Preia date noi
    S-->>A: Returnează date curente
    A->>L: Actualizează cache-ul
    A->>U: Actualizează interfața cu date noi
Loading

Sarcină: Implementați sistemul de actualizare a datelor

Vom crea un sistem care preia automat date proaspete de pe server, menținând avantajele gestionării stării persistente.

Pasul 1: Creați funcția de actualizare a datelor contului

async function updateAccountData() {
  const account = state.account;
  if (!account) {
    return logout();
  }

  const data = await getAccount(account.user);
  if (data.error) {
    return logout();
  }

  updateState('account', data);
}

Logica acestei funcții:

  • Verifică dacă utilizatorul este autentificat (există state.account)
  • Redirecționează către logout dacă nu există o sesiune validă
  • Preia date noi despre cont de la server folosind funcția getAccount() existentă
  • Gestionează cu eleganță erorile serverului prin logout pentru sesiunile invalide
  • Actualizează starea cu date proaspete utilizând sistemul nostru controlat de update
  • Declanșează persistența automată în localStorage prin funcția updateState()

Pasul 2: Creați handlerul de actualizare a dashboardului

async function refresh() {
  await updateAccountData();
  updateDashboard();
}

Ce realizează această funcție de reîmprospătare:

  • Coordonează procesul de actualizare a datelor și actualizarea UI
  • Așteaptă ca datele proaspete să se încarce înainte de actualizarea vizualizării
  • Asigură că dashboardul afișează cele mai recente informații
  • Menține o separare clară între gestionarea datelor și actualizările UI

Pasul 3: Integrați cu sistemul de rutare

Actualizați configurația rutei pentru a declanșa automat reîmprospătarea:

const routes = {
  '/login': { templateId: 'login' },
  '/dashboard': { templateId: 'dashboard', init: refresh }
};

Cum funcționează această integrare:

  • Execută funcția de reîmprospătare de fiecare dată când se încarcă ruta dashboard
  • Asigură afișarea datelor proaspete când utilizatorii navighează spre dashboard
  • Menține structura rutelor existente adăugând prospețimea datelor
  • Oferă un pattern consistent pentru inițializarea specifică fiecărei rute

Testarea sistemului de actualizare a datelor:

  1. Autentificați-vă în aplicația bancară
  2. Rulați comanda curl menționată anterior pentru a crea o nouă tranzacție
  3. Reîncărcați pagina dashboard sau navigați în altă pagină și apoi înapoi
  4. Verificați că noua tranzacție apare imediat

🎉 Echilibrul perfect atins: Aplicația dvs. combină acum experiența fluidă a stării persistente cu acuratețea datelor proaspete de pe server!

📈 Cronologia stăpânirii managementului de stare

timeline
    title Călătoria Profesională în Gestionarea Stării
    
    section Recunoașterea Problemei
        Diagnosticarea Problemelor de Stare
            : Identificarea problemelor de pierdere a sesiunii
            : Înțelegerea problemelor de actualizare dispersată
            : Recunoașterea nevoilor arhitecturale
    
    section Baza Arhitecturii
        Designul Stării Centralizate
            : Crearea obiectelor unificate de stare
            : Implementarea modelelor controlate de actualizare
            : Stabilirea principiilor imuabile
        
        Actualizări Predictibile
            : Stăpânirea utilizării Object.freeze()
            : Construirea sistemelor prietenoase pentru depanare
            : Crearea modelelor scalabile
    
    section Măiestria Persistenței
        Integrarea localStorage
            : Gestionarea serializării JSON
            : Implementarea sincronizării automate
            : Crearea continuității sesiunii
        
        Echilibrul Prospețimii Datelor
            : Abordarea provocărilor cu vechimea datelor
            : Construirea mecanismelor de reîmprospătare
            : Optimizarea performanței versus acuratețea
    
    section Modele Profesionale
        Sisteme Pregătite pentru Producție
            : Implementarea gestionării erorilor
            : Crearea arhitecturilor ușor de întreținut
            : Urmarea celor mai bune practici din industrie
        
        Capabilități Avansate
            : Pregătit pentru integrarea cu cadre de lucru
            : Pregătit pentru nevoi complexe de stare
            : Fundament pentru funcționalități în timp real
Loading

🎓 Milestone de absolvire: Ați construit cu succes un sistem complet de management al stării folosind aceleași principii care alimentează Redux, Vuex și alte biblioteci profesionale de stare. Aceste pattern-uri scală de la aplicații simple la aplicații enterprise.

🔄 Capabilități de nivel următor:

  • Pregătit să stăpâniți framework-uri de management al stării (Redux, Zustand, Pinia)
  • Pregătit să implementați funcționalități în timp real cu WebSockets
  • Echipat să construiți Progressive Web Apps offline-first
  • Fundamente puse pentru pattern-uri avansate precum mașini de stare și observatori

Provocarea agentului GitHub Copilot 🚀

Folosiți modul Agent pentru a finaliza următoarea provocare:

Descriere: Implementați un sistem cuprinzător de management al stării cu funcționalitate undo/redo pentru aplicația bancară. Această provocare vă va ajuta să exersați concepte avansate de management al stării, inclusiv urmărirea istoricului stării, actualizări imutabile și sincronizarea interfeței utilizator.

Prompt: Creați un sistem îmbunătățit de management al stării care să includă: 1) un array pentru istoricul stărilor care să urmărească toate stările anterioare, 2) funcții undo și redo care să revină la stări anterioare, 3) butoane UI pentru operațiunile undo/redo în dashboard, 4) o limită maximă de istoric de 10 stări pentru a preveni problemele de memorie, și 5) curățarea corespunzătoare a istoricului când utilizatorul se deconectează. Asigurați funcționarea undo/redo cu modificările soldului contului și persistența în urma reîncărcărilor browserului.

Aflați mai multe despre modul agent aici.

🚀 Provocare: Optimizarea stocării

Implementarea dvs. gestionează acum eficient sesiunile utilizatorilor, reîmprospătarea datelor și managementul stării. Totuși, luați în considerare dacă abordarea curentă echilibrează optim eficiența stocării cu funcționalitatea.

Ca maeștrii șahului care disting între piese esențiale și pioni sacrificabili, un management eficient al stării necesită identificarea datelor care trebuie să persiste față de cele care trebuie mereu obținute proaspete de pe server.

Analiză de optimizare:

Evaluați implementarea actuală a localStorage și reflectați asupra acestor întrebări strategice:

  • Care este informația minimă necesară pentru a menține autentificarea utilizatorului?
  • Ce date se schimbă suficient de frecvent încât caching-ul local aduce puțin beneficiu?
  • Cum poate optimizarea stocării să îmbunătățească performanța fără a degrada experiența utilizatorului?

Acest tip de analiză arhitecturală îi diferențiază pe dezvoltatorii experimentați care consideră atât funcționalitatea, cât și eficiența în soluțiile lor.

Strategie de implementare:

  • Identificați datele esențiale care trebuie să persiste (probabil doar identificarea utilizatorului)
  • Modificați implementarea localStorage pentru a stoca doar datele critice de sesiune
  • Asigurați încărcarea întotdeauna a datelor proaspete de pe server la vizitele pe dashboard
  • Testați că abordarea optimizată menține aceeași experiență a utilizatorului

Considerații avansate:

  • Comparați compromisurile între stocarea datelor complete ale contului versus doar a token-urilor de autentificare
  • Documentați deciziile și raționamentele pentru membrii echipei viitori

Această provocare vă va ajuta să gândiți ca un dezvoltator profesionist, care ia în calcul atât experiența utilizatorului, cât și eficiența aplicației. Luați-vă timpul să experimentați diferite abordări!

Chestionar post-lectură

Chestionar post-lectură

Tema

Implementați dialogul „Adaugă tranzacție”

Iată un exemplu de rezultat după finalizarea temei:

Captură de ecran care arată un exemplu de dialog „Adaugă tranzacție”


Avertisment:
Acest document a fost tradus folosind serviciul de traducere automată AI Co-op Translator. Deși ne străduim pentru acuratețe, vă rugăm să rețineți că traducerile automate pot conține erori sau inexactități. Documentul original în limba sa nativă trebuie considerat sursa autoritară. Pentru informații critice, se recomandă traducerea profesională realizată de un specialist uman. Nu ne asumăm răspunderea pentru orice neînțelegeri sau interpretări greșite rezultate din utilizarea acestei traduceri.