# 銀行アプリを作成するパート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(Asynchronous JavaScript and XML)](https://en.wikipedia.org/wiki/Ajax_(programming))と呼ばれる新しい技術が登場しました。この技術により、JavaScriptを使用してサーバーから非同期でデータを送受信し、HTMLページをリロードせずに更新することが可能になり、より高速な更新とスムーズなユーザー操作が実現しました。サーバーから新しいデータを受信すると、[DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model) APIを使用して現在のHTMLページをJavaScriptで更新できます。このアプローチは進化を遂げ、現在では[*シングルページアプリケーション*(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)も実装しており、これはPromiseを使用し、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`は[`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET) HTTPリクエストを作成します。 ✅ `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