JavaScript は、必要に応じていつでもサーバへリクエストを送信し、新しい情報を読み込むことができます。
例えば、次のようなことができます:
- 注文を送信する
- ユーザ情報を読み込む
- サーバから最新の更新情報を受け取る
- …など
…そしてこれらはすべてページをリロードすることなく行うことができます。
それを表す包括的な用語 “AJAX” (Asynchronous Javascript And Xml)があります。XML を使う必要はありません: この用語は昔から来ています。
ネットワークリクエストを送信し、サーバから情報を取得するための様々な方法があります。
fetch() メソッドはモダンで多目的に利用できるため、これから始めましょう。fetch は数年間進化と改善を続けています。今のところサポートはブラウザの間でとてもしっかりしています。
基本構文は次の通りです:
let promise = fetch(url, [options])
url– アクセスする URLoptions– オプションのパラメータ: メソッドやヘッダなど
ブラウザはすぐにリクエストを開始し、promise を返します。
レスポンスの取得は通常2段階のプロセスになります。
promise は、サーバがヘッダを応答するとすぐに組み込みの Response クラスのオブジェクトで resolve します。
そのため、HTTP ステータスをチェックすることで、リクエストが成功したのか失敗したのかを確認したり、ヘッダをチェックすることができます。が、まだ本文は持っていません。
promise は fetch が HTTP リクエストを作るすることができなかった場合、例えば ネットワークの問題やそのようなサイトがない場合に reject します。404 や 500 のような HTTP エラーも通常のフローとみなされます。
レスポンスのプロパティでそれらを確認することができます。:
ok– boolean, HTTP ステータスコードが 200-299 の場合trueです。status– HTTP ステータスコード.
例:
let response = await fetch(url);
if (response.ok) { // HTTP ステータスが 200-299 の場合
// レスポンスの本文を取得(後述)
let json = await response.json();
} else {
alert("HTTP-Error: " + response.status);
}
レスポンスの本文を取得するには、追加のメソッド呼び出しが必要です。
Response は様々な形式で本文にアクセスするための、複数の promise ベースのメソッドを提供しています。:
response.json()– レスポンスを JSON オブジェクトとしてパースしますresponse.text()– レスポンスをテキストとして返しますresponse.formData()– FormData オブジェクト(form/multipart encoding) として返します,response.blob()– Blob (型付きのバイナリデータ) としてレスポンスを返します,response.arrayBuffer()– ArrayBuffer (純粋なバイナリデータ) としてレスポンスを返します,- 加えて,
response.bodyは ReadableStream オブジェクトで、本文をチャンク毎に読むことができます。後ほど例を見ていきましょう。
例えば、ここでは Github から最新のコミットの JSON オブジェクトを取得します。:
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits');
let commits = await response.json(); // レスポンスの本文を読み JSON としてパースする
alert(commits[0].author.login);
もしくは、純粋な promise 構文を使用した場合は次のようになります:
fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits')
.then(response => response.json())
.then(commits => alert(commits[0].author.login));
テキストを取得するには:
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits');
let text = await response.text(); // レスポンスボディをテキストとして読む
alert(text.slice(0, 80) + '...');
また、バイナリの例では、画像を取得して表示してみましょう(blob に対する操作の詳細については、チャプター Blob を参照してください)。:
let response = await fetch('/article/fetch/logo-fetch.svg');
let blob = await response.blob(); // Blob オブジェクトとしてダウンロード
// <img> を作成
let img = document.createElement('img');
img.style = 'position:fixed;top:10px;left:10px;width:100px';
document.body.append(img);
// 表示
img.src = URL.createObjectURL(blob);
setTimeout(() => { // 3秒後に隠す
img.remove();
URL.revokeObjectURL(img.src);
}, 3000);
本文のパース方法は1つだけ選ぶことができます。
もし response.text() でレスポンスを取得した後、response.json() は動作しません。本文のコンテンツは既に処理されているためです。
let text = await response.text(); // 本文を返す
let parsed = await response.json(); // 失敗 (既に本文は処理済み)
Headers
response.headers には、Mapライクなヘッダオブジェクトがあります。
個々のヘッダを取得したり、それらをイテレートすることができます。
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits');
// ヘッダを1つ取得
alert(response.headers.get('Content-Type')); // application/json; charset=utf-8
// すべてのヘッダをイテレート
for (let [key, value] of response.headers) {
alert(`${key} = ${value}`);
}
ヘッダを設定するには、次のように headers オプションを使用します:
let response = fetch(protectedUrl, {
headers: {
Authentication: 'abcdef'
}
});
…しかし、設定できない 禁止された HTTP ヘッダ のリストがあります。:
Accept-Charset,Accept-EncodingAccess-Control-Request-HeadersAccess-Control-Request-MethodConnectionContent-LengthCookie,Cookie2DateDNTExpectHostKeep-AliveOriginRefererTETrailer