HTTP通信
アプリケーションが実行できるようになったので、次はGitHubのAPIを呼び出す処理を実装していきます。 当然ですが、GitHubのAPIを呼び出すためにはHTTP通信をする必要があります。 ウェブブラウザ上でJavaScriptからHTTP通信するために、Fetch APIという機能を使います。
Fetch API
Fetch APIはHTTP通信を行いリソースを取得するためのAPIです Fetch APIを使うことで、ページ全体を再読み込みすることなく指定したURLからデータを取得できます。 Fetch APIは同じくHTTP通信を扱うXMLHttpRequestと似たAPIですが、より強力で柔軟な操作が可能です。
GitHubが提供している、ユーザー情報を取得するためのWebAPIを呼び出すコードは次のようになります。
リクエストを送信するためには、グローバルスコープのfetch
メソッドを呼び出します。
fetch
メソッドにURLを与えることで、HTTPリクエストが作成され、サーバーとのHTTP通信を開始します。
fetch(`https://api.github.com/users/${userId}`);
レスポンスの受け取り
GitHubのAPIに対してHTTPリクエストを送信しましたが、まだレスポンスを受け取る処理を書いていません。 次はサーバーから返却されたレスポンスのログをコンソールに出力する処理を実装します。
fetch
メソッドはPromise
を返します。これはリクエストのレスポンスを表すResponse
オブジェクトでresolveされます。
送信したリクエストにレスポンスが返却されると、then
コールバックが呼び出されます。
次のように、Response
オブジェクトのstatus
プロパティからはHTTPレスポンスのステータスコードが取得できます。
また、json
メソッドもPromise
を返します。これは HTTPレスポンスをJSONとしてパースしたオブジェクトでresolveされます。
fetch(`https://api.github.com/users/${userId}`)
.then(response => {
console.log(response.status); // => 200
response.json().then(userInfo => {
// JSONパースされたオブジェクトが渡される
console.log(userInfo); // => {...}
});
});
エラーハンドリング
HTTP通信にはエラーがつきものです。
そのためFetch APIを使った通信においても、エラーをハンドリングする必要があります。
サーバーとの通信に際してネットワークエラーが発生した場合は、ネットワークエラーを表すNetworkError
オブジェクトでrejectされたPromise
が返されます。
すなわち、then
メソッドの第2引数かcatch
メソッドのコールバック関数が呼び出されます。
fetch(`https://api.github.com/users/${userId}`)
.then(response => {
console.log(response.status);
response.json().then(userInfo => {
console.log(userInfo);
});
}).catch(error => {
console.error("ネットワークエラー", error);
});
一方で、リクエストが成功したかどうかはResponse
オブジェクトのok
プロパティで認識できます。
ok
プロパティは、HTTPステータスコードが200番台であればtrue
を返し、400や500番台であればfalse
を返します。
次のように、ok
プロパティがfalse
であるサーバーエラーをハンドリングできます。
fetch(`https://api.github.com/users/${userId}`)
.then(response => {
console.log(response.status);
// エラーレスポンスが返されたことを検知する
if (!response.ok) {
console.error("サーバーエラー", response);
} else {
response.json().then(userInfo => {
console.log(userInfo);
});
}
}).catch(error => {
console.error("ネットワークエラー", error);
});
ここまでの内容をまとめ、GitHubからユーザー情報を取得する関数をgetUserInfo
という名前で定義します。
function getUserInfo(userId) {
fetch(`https://api.github.com/users/${userId}`)
.then(response => {
console.log(response.status);
// エラーレスポンスが返されたことを検知する
if (!response.ok) {
console.error("サーバーエラー", response);
} else {
response.json().then(userInfo => {
console.log(userInfo);
});
}
}).catch(error => {
console.error("ネットワークエラー", error);
});
}
index.jsでは関数を定義しているだけで、呼び出しは行っていません。
ページを読み込むたびにGitHubのAPIを呼び出すと、呼び出し回数の制限を超えるおそれがあります。
呼び出し回数の制限を超えると、APIからのレスポンスがステータスコード403のサーバーエラーになってしまいます。
そこでgetUserInfo
関数を呼び出すため、HTMLドキュメント側にボタンを追加します。
ボタンのclickイベントでgetUserInfo
関数を呼び出し、固定のユーザーIDを引数として与えています。
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>Ajax Example</title>
</head>
<body>
<h2>GitHub User Info</h2>
<button onclick="getUserInfo('js-primer-example');">Get user info</button>
<script src="index.js"></script>
</body>
</html>
準備ができたら、ローカルサーバーを立ち上げてindex.htmlにアクセスしましょう。 ボタンを押すとHTTP通信が行われ、コンソールにステータスコードとレスポンスのログが出力されます。
また、開発者ツールのネットワーク画面を開くと、確かにGitHubのサーバーに対してHTTP通信が行われていることを確認できます。