# Създаване на Банкова Приложение Част 3: Методи за Извличане и Използване на Данни ## Предварителен Тест [Предварителен тест](https://ff-quizzes.netlify.app/web/quiz/45) ### Въведение В основата на всяко уеб приложение стои *данните*. Данните могат да приемат различни форми, но основната им цел винаги е да предоставят информация на потребителя. С развитието на уеб приложенията, които стават все по-интерактивни и сложни, начинът, по който потребителят достъпва и взаимодейства с информацията, е ключова част от уеб разработката. В този урок ще разгледаме как да извличаме данни от сървър асинхронно и как да използваме тези данни, за да показваме информация на уеб страница без презареждане на HTML. ### Предварителни изисквания Трябва да сте създали [Формата за Вход и Регистрация](../2-forms/README.md) като част от уеб приложението за този урок. Също така трябва да инсталирате [Node.js](https://nodejs.org) и [да стартирате сървърния API](../api/README.md) локално, за да получите данни за акаунта. Можете да тествате дали сървърът работи правилно, като изпълните следната команда в терминала: ```sh curl http://localhost:5000/api # -> should return "Bank API v1.0.0" as a result ``` --- ## AJAX и извличане на данни Традиционните уеб сайтове обновяват съдържанието, когато потребителят избере линк или изпрати данни чрез форма, като презареждат цялата HTML страница. Всеки път, когато трябва да се заредят нови данни, уеб сървърът връща изцяло нова HTML страница, която трябва да бъде обработена от браузъра, прекъсвайки текущото действие на потребителя и ограничавайки взаимодействията по време на презареждането. Този работен процес е известен като *Многостранично Приложение* или *MPA*.  С развитието на по-сложни и интерактивни уеб приложения се появи нова техника, наречена [AJAX (Асинхронен JavaScript и XML)](https://en.wikipedia.org/wiki/Ajax_(programming)). Тази техника позволява на уеб приложенията да изпращат и получават данни от сървър асинхронно с помощта на JavaScript, без да се налага презареждане на HTML страницата, което води до по-бързи актуализации и по-гладки взаимодействия с потребителя. Когато нови данни се получат от сървъра, текущата HTML страница може да бъде обновена с JavaScript чрез [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model) API. С времето този подход еволюира в това, което сега наричаме [*Едностранично Приложение* или *SPA*](https://en.wikipedia.org/wiki/Single-page_application).  Когато AJAX беше въведен за първи път, единственият наличен API за асинхронно извличане на данни беше [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Но съвременните браузъри вече поддържат по-удобния и мощен [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), който използва обещания (promises) и е по-подходящ за работа с JSON данни. > Въпреки че всички съвременни браузъри поддържат `Fetch API`, ако искате вашето уеб приложение да работи на стари браузъри, винаги е добра идея да проверите [таблицата за съвместимост на caniuse.com](https://caniuse.com/fetch). ### Задача В [предишния урок](../2-forms/README.md) имплементирахме формата за регистрация, за да създадем акаунт. Сега ще добавим код за вход с вече съществуващ акаунт и извличане на неговите данни. Отворете файла `app.js` и добавете нова функция `login`: ```js async function login() { const loginForm = document.getElementById('loginForm') const user = loginForm.user.value; } ``` Тук започваме с извличане на елемента на формата чрез `getElementById()`, след което получаваме потребителското име от полето за вход с `loginForm.user.value`. Всеки контрол на формата може да бъде достъпен чрез неговото име (зададено в HTML чрез атрибута `name`) като свойство на формата. По подобен начин на това, което направихме за регистрацията, ще създадем друга функция за изпълнение на заявка към сървъра, но този път за извличане на данни за акаунта: ```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' }; } } ``` Използваме `fetch` API, за да заявим данните асинхронно от сървъра, но този път не се нуждаем от допълнителни параметри освен URL адреса, тъй като само извличаме данни. По подразбиране `fetch` създава HTTP заявка от тип [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET), което е точно това, което ни трябва тук. ✅ `encodeURIComponent()` е функция, която кодира специални символи за URL. Какви проблеми бихме могли да имаме, ако не извикаме тази функция и използваме директно стойността на `user` в URL? Сега нека актуализираме нашата функция `login`, за да използва `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'); } ``` Първо, тъй като `getAccount` е асинхронна функция, трябва да я съчетаем с ключовата дума `await`, за да изчакаме резултата от сървъра. Както при всяка заявка към сървър, трябва да се справим и с грешки. Засега ще добавим само съобщение за грешка в конзолата и ще се върнем към това по-късно. След това трябва да съхраним данните някъде, за да можем по-късно да ги използваме за показване на информацията на таблото. Тъй като променливата `account` все още не съществува, ще създадем глобална променлива за нея в началото на нашия файл: ```js let account = null; ``` След като данните за потребителя са запазени в променлива, можем да преминем от страницата за *вход* към *таблото* с помощта на функцията `navigate()`, която вече имаме. Накрая, трябва да извикаме нашата функция `login`, когато формата за вход е изпратена, като модифицираме HTML: ```html