# Создание банковского приложения, часть 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 через API [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model). Со временем этот подход эволюционировал в то, что сейчас называется [*одностраничным приложением* или *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), который использует промисы и лучше подходит для работы с данными в формате 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' }; } } ``` Мы используем API `fetch` для асинхронного запроса данных с сервера, но на этот раз нам не нужны дополнительные параметры, кроме 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