# Створення банківського додатку, частина 3: Методи отримання та використання даних Уявіть комп'ютер на борту Enterprise у Star Trek — коли капітан Пікард запитує статус корабля, інформація з'являється миттєво, без перезавантаження інтерфейсу. Саме такий плавний потік інформації ми створюємо тут за допомогою динамічного отримання даних. Зараз ваш банківський додаток схожий на друковану газету — інформативний, але статичний. Ми перетворимо його на щось схоже на центр управління NASA, де дані постійно оновлюються в реальному часі, не перериваючи робочий процес користувача. Ви навчитеся асинхронно взаємодіяти з серверами, обробляти дані, які надходять у різний час, і перетворювати необроблену інформацію на щось корисне для ваших користувачів. Це різниця між демонстраційним додатком і програмним забезпеченням, готовим до використання. ## ⚡ Що можна зробити за наступні 5 хвилин **Швидкий старт для зайнятих розробників** ```mermaid flowchart LR A[⚡ 5 minutes] --> B[Set up API server] B --> C[Test fetch with curl] C --> D[Create login function] D --> E[See data in action] ``` - **Хвилина 1-2**: Запустіть сервер API (`cd api && npm start`) і протестуйте з'єднання - **Хвилина 3**: Створіть базову функцію `getAccount()` за допомогою fetch - **Хвилина 4**: Підключіть форму входу за допомогою `action="javascript:login()"` - **Хвилина 5**: Протестуйте вхід і спостерігайте, як дані облікового запису з'являються в консолі **Швидкі команди для тестування**: ```bash # Verify API is running curl http://localhost:5000/api # Test account data fetch curl http://localhost:5000/api/accounts/test ``` **Чому це важливо**: За 5 хвилин ви побачите магію асинхронного отримання даних, яка є основою кожного сучасного веб-додатку. Це фундамент, який робить додатки чуйними та живими. ## 🗺️ Ваш навчальний шлях через веб-додатки, керовані даними ```mermaid journey title From Static Pages to Dynamic Applications section Understanding the Evolution Traditional page reloads: 3: You Discover AJAX/SPA benefits: 5: You Master Fetch API patterns: 7: You section Building Authentication Create login functions: 4: You Handle async operations: 6: You Manage user sessions: 8: You section Dynamic UI Updates Learn DOM manipulation: 5: You Build transaction displays: 7: You Create responsive dashboards: 9: You section Professional Patterns Template-based rendering: 6: You Error handling strategies: 7: You Performance optimization: 8: You ``` **Мета вашого навчання**: До кінця цього уроку ви зрозумієте, як сучасні веб-додатки отримують, обробляють і динамічно відображають дані, створюючи плавний користувацький досвід, якого ми очікуємо від професійних додатків. ## Попереднє опитування [Попереднє опитування](https://ff-quizzes.netlify.app/web/quiz/45) ### Передумови Перед тим як зануритися в отримання даних, переконайтеся, що у вас готові наступні компоненти: - **Попередній урок**: Завершіть [Форму входу та реєстрації](../2-forms/README.md) — ми будемо будувати на цій основі - **Локальний сервер**: Встановіть [Node.js](https://nodejs.org) і [запустіть сервер API](../api/README.md), щоб надати дані облікового запису - **З'єднання API**: Перевірте з'єднання вашого сервера за допомогою цієї команди: ```bash curl http://localhost:5000/api # Expected response: "Bank API v1.0.0" ``` Цей швидкий тест гарантує правильну комунікацію всіх компонентів: - Перевіряє, чи Node.js працює правильно на вашій системі - Підтверджує, що сервер API активний і відповідає - Переконується, що ваш додаток може досягти сервера (як перевірка радіозв'язку перед місією) ## 🧠 Огляд екосистеми управління даними ```mermaid mindmap root((Data Management)) Authentication Flow Login Process Form Validation Credential Verification Session Management User State Global Account Object Navigation Guards Error Handling API Communication Fetch Patterns GET Requests POST Requests Error Responses Data Formats JSON Processing URL Encoding Response Parsing Dynamic UI Updates DOM Manipulation Safe Text Updates Element Creation Template Cloning User Experience Real-time Updates Error Messages Loading States Security Considerations XSS Prevention textContent Usage Input Sanitization Safe HTML Creation CORS Handling Cross-Origin Requests Header Configuration Development Setup ``` **Основний принцип**: Сучасні веб-додатки — це системи оркестрації даних, які координують взаємодію між користувацькими інтерфейсами, серверними API та моделями безпеки браузера, створюючи плавний і чуйний досвід. --- ## Розуміння отримання даних у сучасних веб-додатках Спосіб, яким веб-додатки обробляють дані, значно еволюціонував за останні два десятиліття. Розуміння цієї еволюції допоможе вам оцінити, чому сучасні техніки, такі як AJAX і Fetch API, є настільки потужними і чому вони стали необхідними інструментами для веб-розробників. Давайте дослідимо, як працювали традиційні веб-сайти порівняно з динамічними, чуйними додатками, які ми створюємо сьогодні. ### Традиційні багатосторінкові додатки (MPA) На початку розвитку вебу кожен клік був схожий на зміну каналів на старому телевізорі — екран ставав порожнім, а потім повільно налаштовувався на новий контент. Це була реальність ранніх веб-додатків, де кожна взаємодія означала повне перезавантаження сторінки. ```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) ``` ![Робочий процес оновлення в багатосторінковому додатку](../../../../translated_images/mpa.7f7375a1a2d4aa779d3f928a2aaaf9ad76bcdeb05cfce2dc27ab126024050f51.uk.png) **Чому цей підхід здавався незручним:** - Кожен клік означав повне перезавантаження сторінки - Користувачів переривали ці дратівливі спалахи сторінки - Ваше інтернет-з'єднання працювало понаднормово, завантажуючи той самий заголовок і підвал знову і знову - Додатки більше нагадували перегляд картотеки, ніж використання програмного забезпечення ### Сучасні односторінкові додатки (SPA) AJAX (асинхронний JavaScript і XML) повністю змінив цей підхід. Як модульний дизайн Міжнародної космічної станції, де астронавти можуть замінювати окремі компоненти без перебудови всієї структури, AJAX дозволяє нам оновлювати конкретні частини веб-сторінки без перезавантаження всього. Незважаючи на те, що в назві згадується XML, сьогодні ми здебільшого використовуємо JSON, але основний принцип залишається: оновлювати лише те, що потрібно змінити. ```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) ``` ![Робочий процес оновлення в односторінковому додатку](../../../../translated_images/spa.268ec73b41f992c2a21ef9294235c6ae597b3c37e2c03f0494c2d8857325cc57.uk.png) **Чому SPA здаються набагато кращими:** - Оновлюються лише ті частини, які дійсно змінилися (розумно, правда?) - Більше ніяких різких переривань — ваші користувачі залишаються в потоці - Менше даних передається через мережу, що означає швидше завантаження - Все здається швидким і чуйним, як додатки на вашому телефоні ### Еволюція до сучасного Fetch API Сучасні браузери надають [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), який замінює старий [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Як різниця між використанням телеграфу і електронної пошти, Fetch API використовує promises для чистішого асинхронного коду і природно обробляє JSON. | Функція | XMLHttpRequest | Fetch API | |---------|----------------|----------| | **Синтаксис** | Складний, на основі callback | Чистий, на основі promise | | **Обробка JSON** | Потрібне ручне парсування | Вбудований метод `.json()` | | **Обробка помилок** | Обмежена інформація про помилки | Детальна інформація про помилки | | **Сучасна підтримка** | Сумісність зі старими версіями | Підтримка ES6+ promises і async/await | > 💡 **Сумісність з браузерами**: Хороші новини — Fetch API працює у всіх сучасних браузерах! Якщо вам цікаві конкретні версії, [caniuse.com](https://caniuse.com/fetch) має повну історію сумісності. > **Основний висновок:** - Чудово працює в Chrome, Firefox, Safari та Edge (загалом скрізь, де є ваші користувачі) - Лише Internet Explorer потребує додаткової допомоги (і чесно кажучи, час відпустити IE) - Ідеально підходить для елегантних async/await паттернів, які ми будемо використовувати пізніше ### Реалізація входу користувача та отримання даних Тепер давайте реалізуємо систему входу, яка перетворює ваш банківський додаток зі статичного дисплея на функціональний додаток. Як протоколи автентифікації, що використовуються в захищених військових об'єктах, ми перевіримо облікові дані користувача, а потім надамо доступ до його конкретних даних. Ми будемо будувати це поступово, починаючи з базової автентифікації, а потім додаючи можливості отримання даних. #### Крок 1: Створення основи функції входу Відкрийте ваш файл `app.js` і додайте нову функцію `login`. Вона буде обробляти процес автентифікації користувача: ```javascript async function login() { const loginForm = document.getElementById('loginForm'); const user = loginForm.user.value; } ``` **Розберемо це:** - Ключове слово `async`? Воно говорить JavaScript: "гей, ця функція може потребувати очікування" - Ми отримуємо нашу форму зі сторінки (нічого складного, просто знаходимо її за ID) - Потім витягуємо те, що користувач ввів як своє ім'я користувача - Ось цікавий трюк: ви можете отримати доступ до будь-якого елемента форми за його атрибутом `name` — не потрібно додаткових викликів getElementById! > 💡 **Шаблон доступу до форми**: До кожного елемента форми можна отримати доступ за його ім'ям (встановленим у HTML за допомогою атрибута `name`) як до властивості елемента форми. Це забезпечує чистий і читабельний спосіб отримання даних форми. #### Крок 2: Створення функції отримання даних облікового запису Далі ми створимо спеціальну функцію для отримання даних облікового запису з сервера. Це слідує тому ж шаблону, що й ваша функція реєстрації, але зосереджено на отриманні даних: ```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' }; } } ``` **Що робить цей код:** - **Використовує** сучасний `fetch` API для асинхронного запиту даних - **Формує** URL запиту GET з параметром імені користувача - **Застосовує** `encodeURIComponent()` для безпечної обробки спеціальних символів у URL - **Перетворює** відповідь у формат JSON для зручної маніпуляції даними - **Обробляє** помилки акуратно, повертаючи об'єкт помилки замість аварійного завершення > ⚠️ **Примітка щодо безпеки**: Функція `encodeURIComponent()` обробляє спеціальні символи в URL. Як системи кодування, що використовуються в морських комунікаціях, вона гарантує, що ваше повідомлення прибуде саме так, як задумано, запобігаючи неправильному тлумаченню символів, таких як "#" або "&". > **Чому це важливо:** - Запобігає порушенню URL через спеціальні символи - Захищає від атак маніпуляції URL - Гарантує, що сервер отримує потрібні дані - Дотримується практик безпечного кодування #### Розуміння HTTP GET-запитів Ось що може вас здивувати: коли ви використовуєте `fetch` без додаткових опцій, він автоматично створює [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET) запит. Це ідеально підходить для того, що ми робимо — запитуємо сервер: "гей, чи можу я побачити дані цього користувача?" Думайте про GET-запити як про ввічливе прохання позичити книгу в бібліотеці — ви запитуєте, щоб побачити щось, що вже існує. POST-запити (які ми використовували для реєстрації) більше схожі на подання нової книги для додавання до колекції. | GET-запит | POST-запит | |-----------|------------| | **Призначення** | Отримання існуючих даних | Надсилання нових даних на сервер | | **Параметри** | У шляху URL/рядку запиту | У тілі запиту | | **Кешування** | Може кешуватися браузерами | Зазвичай не кешується | | **Безпека** | Видно в URL/журналах | Приховано в тілі запиту | ```mermaid sequenceDiagram participant B as Browser participant S as Server Note over B,S: GET Request (Data Retrieval) B->>S: GET /api/accounts/test S-->>B: 200 OK + Account Data Note over B,S: POST Request (Data Submission) B->>S: POST /api/accounts + New Account Data S-->>B: 201 Created + Confirmation Note over B,S: Error Handling B->>S: GET /api/accounts/nonexistent S-->>B: 404 Not Found + Error Message ``` #### Крок 3: Об'єднання всього разом Тепер найзадовільніша частина — давайте підключимо вашу функцію отримання даних облікового запису до процесу входу. Тут все стає на свої місця: ```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'); } ``` Ця функція слідує чіткому порядку: - Витягує ім'я користувача з введення форми - Запитує дані облікового запису користувача з сервера - Обробляє будь-які помилки, що виникають під час процесу - Зберігає дані облікового запису та переходить на панель управління після успішного входу > 🎯 **Паттерн Async/Await**: Оскільки `getAccount` є асинхронною функцією, ми використовуємо ключове слово `await`, щоб призупинити виконання до отримання відповіді від сервера. Це запобігає продовженню коду з невизначеними даними. #### Крок 4: Створення місця для ваших даних Вашому додатку потрібне місце, щоб зберігати інформацію про обліковий запис після її завантаження. Думайте про це як про короткострокову пам'ять вашого додатку — місце, де зберігаються дані поточного користувача. Додайте цей рядок на початку вашого файлу `app.js`: ```javascript // This holds the current user's account data let account = null; ``` **Чому це потрібно:** - Зберігає дані облікового запису доступними з будь-якого місця вашого додатку - Початок з `null` означає "поки що ніхто не увійшов" - Оновлюється, коли хтось успішно входить або реєструється - Діє як єдине джерело правди — ніякої плутанини щодо того, хто увійшов #### Крок 5: Підключення вашої форми Тепер давайте підключимо вашу нову функцію входу до HTML-форми. Оновіть тег форми таким чином: ```html
``` **Що робить ця невелика зміна:** - Зупиняє форму від виконання її стандартної поведінки "перезавантажити всю сторінку" - Викликає вашу власну функцію JavaScript - Зберігає все плавним і схожим на односторінковий додаток - Дає вам повний контроль над тим, що відбувається, коли користувачі натискають "Вхід" #### Крок 6: Покращення функції реєстрації Для узгодженості оновіть вашу функцію `register`, щоб також зберігати дані облікового запису та переходити на панель управління: ```javascript // Add these lines at the end of your register function account = result; navigate('/dashboard'); ``` **Це покращення забезпечує:** - **Плавний** перехід від реєстрації до панелі управління - **Послідовний** користувацький досвід між процесами входу та реєстрації - **Миттєвий** доступ до даних облікового запису після успішної реєстрації #### Тестування вашої реалізації ```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] ``` **Час протестувати:** 1. Створіть новий обліковий запис, щоб переконатися, що все працює 2. Спробуйте увійти з тими ж обліковими даними 3. Загляньте в консоль вашого браузера (F12), якщо щось здається неправильним 4. Переконайтеся, що ви потрапляєте на панель управління після успішного входу Якщо щось не працює, не панікуйте! Більшість проблем — це прості виправлення, як-от Маніпуляція DOM — це техніка, яка перетворює статичні веб-сторінки на динамічні додатки, що оновлюють свій контент залежно від взаємодії користувача та відповідей сервера. ### Вибір правильного інструменту для роботи Коли справа доходить до оновлення HTML за допомогою JavaScript, у вас є кілька варіантів. Уявіть їх як різні інструменти в ящику для інструментів — кожен ідеально підходить для певних завдань: | Метод | Для чого підходить | Коли використовувати | Рівень безпеки | |-------|--------------------|----------------------|----------------| | `textContent` | Безпечне відображення даних користувача | Завжди, коли потрібно показати текст | ✅ Надійно | | `createElement()` + `append()` | Створення складних макетів | Створення нових секцій/списків | ✅ Безпечно | | `innerHTML` | Встановлення HTML-контенту | ⚠️ Намагайтеся уникати цього | ❌ Ризиковано | #### Безпечний спосіб показу тексту: textContent Властивість [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent) — ваш найкращий друг для відображення даних користувача. Це як охоронець для вашої веб-сторінки — нічого шкідливого не пройде: ```javascript // The safe, reliable way to update text const balanceElement = document.getElementById('balance'); balanceElement.textContent = account.balance; ``` **Переваги textContent:** - Сприймає все як звичайний текст (запобігає виконанню скриптів) - Автоматично очищає існуючий контент - Ефективний для простих текстових оновлень - Забезпечує вбудовану безпеку від шкідливого контенту #### Створення динамічних HTML-елементів Для більш складного контенту комбінуйте [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) з методом [`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); ``` **Розуміння цього підходу:** - **Створює** нові елементи DOM програмно - **Забезпечує** повний контроль над атрибутами та контентом елементів - **Дозволяє** створювати складні, вкладені структури елементів - **Зберігає** безпеку, розділяючи структуру та контент > ⚠️ **Міркування щодо безпеки**: Хоча [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) часто зустрічається в навчальних матеріалах, він може виконувати вбудовані скрипти. Як протоколи безпеки в CERN, що запобігають несанкціонованому виконанню коду, використання `textContent` і `createElement` забезпечує більш безпечні альтернативи. > **Ризики innerHTML:** - Виконує будь-які `