# Budowa aplikacji bankowej, część 3: Metody pobierania i wykorzystywania danych ## Quiz przed wykładem [Quiz przed wykładem](https://ff-quizzes.netlify.app/web/quiz/45) ### Wprowadzenie W centrum każdej aplikacji internetowej znajdują się *dane*. Dane mogą przyjmować różne formy, ale ich głównym celem jest zawsze wyświetlanie informacji użytkownikowi. Wraz z rosnącą interaktywnością i złożonością aplikacji internetowych, sposób, w jaki użytkownik uzyskuje dostęp do informacji i wchodzi z nimi w interakcję, stał się kluczowym elementem tworzenia stron internetowych. W tej lekcji zobaczymy, jak asynchronicznie pobierać dane z serwera i wykorzystywać je do wyświetlania informacji na stronie internetowej bez przeładowywania HTML. ### Wymagania wstępne Musisz mieć zbudowany [formularz logowania i rejestracji](../2-forms/README.md) jako część aplikacji internetowej dla tej lekcji. Musisz również zainstalować [Node.js](https://nodejs.org) i [uruchomić API serwera](../api/README.md) lokalnie, aby uzyskać dane konta. Możesz sprawdzić, czy serwer działa poprawnie, wykonując to polecenie w terminalu: ```sh curl http://localhost:5000/api # -> should return "Bank API v1.0.0" as a result ``` --- ## AJAX i pobieranie danych Tradycyjne strony internetowe aktualizują wyświetlaną zawartość, gdy użytkownik wybiera link lub przesyła dane za pomocą formularza, poprzez przeładowanie całej strony HTML. Za każdym razem, gdy trzeba załadować nowe dane, serwer internetowy zwraca zupełnie nową stronę HTML, którą przetwarza przeglądarka, przerywając bieżące działania użytkownika i ograniczając interakcje podczas przeładowania. Ten sposób działania nazywany jest również *aplikacją wielostronicową* (Multi-Page Application, MPA).  Wraz z rozwojem bardziej złożonych i interaktywnych aplikacji internetowych pojawiła się nowa technika zwana [AJAX (Asynchronous JavaScript and XML)](https://en.wikipedia.org/wiki/Ajax_(programming)). Technika ta pozwala aplikacjom internetowym na asynchroniczne wysyłanie i pobieranie danych z serwera za pomocą JavaScript, bez konieczności przeładowywania strony HTML, co skutkuje szybszymi aktualizacjami i płynniejszymi interakcjami użytkownika. Po otrzymaniu nowych danych z serwera, bieżąca strona HTML może być również aktualizowana za pomocą JavaScript przy użyciu API [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model). Z czasem podejście to ewoluowało w kierunku tego, co obecnie nazywane jest [*aplikacją jednostronicową* (Single-Page Application, SPA)](https://en.wikipedia.org/wiki/Single-page_application).  Gdy AJAX został wprowadzony, jedynym dostępnym API do asynchronicznego pobierania danych było [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Jednak nowoczesne przeglądarki implementują teraz bardziej wygodne i potężne [`Fetch API`](https://developer.mozilla.org/docs/Web/API/Fetch_API), które korzysta z obietnic (promises) i jest lepiej dostosowane do manipulacji danymi JSON. > Chociaż wszystkie nowoczesne przeglądarki obsługują `Fetch API`, jeśli chcesz, aby Twoja aplikacja internetowa działała na starszych przeglądarkach, zawsze warto sprawdzić [tabelę kompatybilności na caniuse.com](https://caniuse.com/fetch). ### Zadanie W [poprzedniej lekcji](../2-forms/README.md) zaimplementowaliśmy formularz rejestracji do tworzenia konta. Teraz dodamy kod do logowania przy użyciu istniejącego konta i pobierania jego danych. Otwórz plik `app.js` i dodaj nową funkcję `login`: ```js async function login() { const loginForm = document.getElementById('loginForm') const user = loginForm.user.value; } ``` Zaczynamy od pobrania elementu formularza za pomocą `getElementById()`, a następnie uzyskujemy nazwę użytkownika z pola wejściowego za pomocą `loginForm.user.value`. Każdy kontroler formularza można uzyskać jako właściwość formularza, korzystając z nazwy (ustawionej w HTML za pomocą atrybutu `name`). Podobnie jak w przypadku rejestracji, stworzymy kolejną funkcję do wykonania żądania serwera, tym razem w celu pobrania danych konta: ```js 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' }; } } ``` Używamy `fetch API`, aby asynchronicznie zażądać danych z serwera, ale tym razem nie potrzebujemy żadnych dodatkowych parametrów poza URL, ponieważ tylko zapytujemy dane. Domyślnie `fetch` tworzy żądanie HTTP typu [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET), co jest dokładnie tym, czego potrzebujemy. ✅ `encodeURIComponent()` to funkcja, która koduje specjalne znaki dla URL. Jakie problemy moglibyśmy napotkać, jeśli nie wywołamy tej funkcji i użyjemy bezpośrednio wartości `user` w URL? Teraz zaktualizujmy naszą funkcję `login`, aby używała `getAccount`: ```js 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'); } ``` Ponieważ `getAccount` jest funkcją asynchroniczną, musimy użyć słowa kluczowego `await`, aby poczekać na wynik serwera. Jak w przypadku każdego żądania serwera, musimy również obsłużyć przypadki błędów. Na razie dodamy tylko komunikat logowania, aby wyświetlić błąd, a później do tego wrócimy. Następnie musimy przechowywać dane gdzieś, aby później móc je wykorzystać do wyświetlenia informacji na pulpicie nawigacyjnym. Ponieważ zmienna `account` jeszcze nie istnieje, stworzymy dla niej zmienną globalną na początku naszego pliku: ```js let account = null; ``` Po zapisaniu danych użytkownika w zmiennej możemy przejść ze strony *login* na *dashboard* za pomocą funkcji `navigate()`, którą już mamy. Na koniec musimy wywołać naszą funkcję `login`, gdy formularz logowania zostanie przesłany, modyfikując HTML: ```html