フェッチ API チュートリアル

fetch() は XMLHttpRequest のアップグレードされたバージョンで、JavaScript スクリプトで HTTP リクエストを行うために使用されます。

ブラウザはこのオブジェクトをネイティブに提供します。この章ではその使用法について詳しく説明します。

基本的な使い方

fetch() の機能は基本的に XMLHttpRequest と同じですが、どちらもサーバーに HTTP リクエストを送信しますが、主な違いが 3 つあります。

(1) fetch() は Promise を使用し、コールバック関数を使用しないため、記述方法が大幅に簡略化され簡潔になります。

(2) 「fetch()」はモジュール設計を採用しており、API は複数のオブジェクト (Response オブジェクト、Request オブジェクト、Headers オブジェクト) に分散されており、対照的に、XMLHttpRequest の API 設計はあまり良くありません。また、入力、出力、ステータスはすべて同じインターフェイスを通じて管理されるため、非常に複雑なコードを簡単に作成できます。

(3) 「fetch()」はデータ ストリーム (Stream オブジェクト) を通じてデータを処理し、チャンクで読み取ることができるため、Web サイトのパフォーマンスの向上とメモリ使用量の削減に役立ちます。大きなファイルが要求されるシナリオや、ネットワーク速度が遅い。 XMLHttpRequest オブジェクトはデータ ストリーミングをサポートしていません。すべてのデータはキャッシュに配置されます。すべてのデータを一度に読み取る前に、すべてのデータが取得されるまで待つ必要があります。

使用法に関しては、fetch() は URL 文字列をパラメータとして受け取り、デフォルトで URL に対して GET リクエストを作成し、Promise オブジェクトを返します。基本的な使い方は以下の通りです。

フェッチ(URL)
  。それから(...)
  。キャッチ(...)

以下はサーバーから JSON データを取得する例です。

fetch('https://api.github.com/users/ruanyf')
  .then(応答 => 応答.json())
  .then(json => console.log(json))
  .catch(err => console.log('リクエストが失敗しました', err));

上記の例では、「fetch()」によって受信される「応答」は Stream オブジェクト であり、その中のデータはこの例では JSON データなので、response.json() メソッドを使用して JSON オブジェクトに変換します。これは非同期操作であり、Promise オブジェクトを返します。

Promise は、セマンティクスを明確にするために await 構文を使用して書き直すことができます。

非同期関数 getJSON() {
  URL = 'https://api.github.com/users/ruanyf';
  試す {
    let 応答 = await fetch(url);
    return await 応答.json();
  } キャッチ (エラー) {
    console.log('リクエストが失敗しました'、エラー);
  }
}

上記の例では、非同期操作中に発生する可能性のあるエラーをキャッチできるように、「await」ステートメントを「try...catch」内に配置する必要があります。

以下の記事では await の記述方法を使用し、.then() の記述方法は使用しなくなります。

応答オブジェクト: HTTP 応答を処理します

Response オブジェクトの同期プロパティ

fetch() リクエストが成功すると、Response オブジェクト を取得します。サーバーのHTTPレスポンスに相当します。

const 応答 = fetch(url) を待ちます。

前述したように、Response に含まれるデータは Stream インターフェースを介して非同期的に読み取られますが、HTTP レスポンスのヘッダー情報 (Headers) に対応する同期属性も含まれており、すぐに読み込むことができます。

非同期関数 fetchText() {
  let response = await fetch('/readme.txt');
  console.log(response.status);
  console.log(response.statusText);
}

上記の例では、response.statusresponse.statusText は Response の同期プロパティであり、すぐに読み取ることができます。

ヘッダ情報の属性には以下のものが含まれます。

応答OK

「Response.ok」プロパティは、リクエストが成功したかどうかを示すブール値を返します。「true」は HTTP リクエストのステータス コード 200 ~ 299 に対応し、「false」はその他のステータス コードに対応します。

応答.ステータス

Response.status プロパティは、HTTP 応答のステータス コードを表す数値を返します (たとえば、リクエストが成功したことを示す 200)。

Response.statusText

Response.statusText プロパティは、HTTP 応答のステータス情報を表す文字列を返します (たとえば、リクエストが成功した後、サーバーは「OK」を返します)。

応答.url

Response.url プロパティは、要求された URL を返します。 URL へのジャンプがある場合、このプロパティは最終 URL を返します。

応答の種類

Response.type プロパティはリクエストのタイプを返します。可能な値は次のとおりです。

  • basic: 通常のリクエスト、つまり同一生成元リクエスト。
  • cors: クロスオリジンリクエスト。
  • error: ネットワーク エラー。主に Service Worker に使用されます。
  • opaque: fetch() リクエストの type 属性が no-cors に設定されている場合、この値が返されます。詳細については、リクエストのセクションを参照してください。 <form> フォームのクロスオリジン リクエストと同様の、単純なクロスオリジン リクエストが発行されることを示します。
  • opaqueredirect: fetch() リクエストの redirect 属性が manual に設定されている場合、この値が返されます。詳細については、リクエストのセクションを参照してください。

応答.リダイレクトされました

Response.redirected プロパティは、リクエストがリダイレクトされたかどうかを示すブール値を返します。

リクエストが成功したかどうかを判断する

fetch() がリクエストを発行した後、非常に重要な点に注意してください。fetch() は、ネットワーク エラーが発生した場合、または接続できない場合にのみエラーを報告します。それ以外の場合は、エラーは報告されません。ただし、リクエストは成功したとみなされます。

これは、サーバーから返されたステータス コードが 4xx または 5xx であっても、fetch() はエラーを報告しないことを意味します (つまり、Promise は rejected ステータスにはなりません)。

Response.status プロパティを通じて HTTP 応答の実際のステータス コードを取得することによってのみ、リクエストが成功したかどうかを判断できます。以下の例を参照してください。

非同期関数 fetchText() {
  let response = await fetch('/readme.txt');
  if (response.status >= 200 && response.status < 300) {
    return await 応答.text();
  } それ以外 {
    新しいエラーをスロー(response.statusText);
  }
}

上記の例では、response.status プロパティは 2xx (200 ~ 299) に等しい場合にのみ成功とみなされます。 fetch() がジャンプステータスコードを自動的に 200 に変換するため、ここでは URL ジャンプ (ステータスコードは 3xx) を考慮する必要はありません。

別の方法は、「response.ok」が「true」であるかどうかを確認することです。

if (response.ok) {
  // リクエストが成功しました
} それ以外 {
  // リクエストが失敗しました
}

Response.headers プロパティ

Response オブジェクトには Response.headers プロパティもあります。これは、 HTTP 応答。

ヘッダー オブジェクトは、「for...of」ループを使用して走査できます。

const 応答 = fetch(url) を待ちます。

for (response.headers の [キー, 値] ) {
  console.log(`${key} : ${value}`);
}

// または
for (response.headers.entries() の [キー, 値]) {
  console.log(`${key} : ${value}`);
}

Headers オブジェクトは、ヘッダーを操作するための次のメソッドを提供します。

  • Headers.get(): 指定されたキー名に基づいてキー値を返します。
  • Headers.has(): ヘッダーが含まれているかどうかを示すブール値を返します。
  • Headers.set(): 指定されたキー名を新しいキー値に設定します。キー名が存在しない場合は追加されます。
  • Headers.append(): ヘッダーを追加します。
  • Headers.delete(): ヘッダーを削除します。
  • Headers.keys(): すべてのキー名を順番に走査できるトラバーサを返します。
  • Headers.values(): すべてのキー値を順番に走査できるトラバーサを返します。
  • Headers.entries(): すべてのキーと値のペア ([key, value]) を順番に走査できるトラバーサを返します。
  • Headers.forEach(): ヘッダーを順番に走査し、各ヘッダーでパラメーター関数を 1 回実行します。

上記のメソッドの一部は、Headers インターフェイスから継承するため、ヘッダーを変更できます。 HTTP 応答の場合、ヘッダーの変更はほとんど重要ではなく、多くのヘッダーは読み取り専用であり、ブラウザーでは変更が許可されません。

これらのメソッドの中で最も一般的に使用されるのは response.headers.get() で、これは特定のヘッダーの値を読み取るために使用されます。

let 応答 = await fetch(url);
response.headers.get('コンテンツタイプ')
// アプリケーション/json; charset=utf-8;

Headers.keys() メソッドと Headers.values() メソッドは、それぞれヘッダー キー名とキー値を走査するために使用されます。

// キー名
for(myHeaders.keys() のキーを許可) {
  コンソール.ログ(キー);
}

// キーの値
for(myHeaders.values() の値を許可) {
  console.log(値);
}

Headers.forEach() メソッドは、すべてのキー値とキー名を反復処理することもできます。

let 応答 = await fetch(url);
response.headers.forEach(
  (値, キー) => console.log(キー, ':', 値)
);

コンテンツの読み取り方法

「Response」オブジェクトは、サーバーから返されるさまざまなタイプのデータに応じてさまざまな読み取りメソッドを提供します。

  • response.text(): テキスト文字列を取得します。
  • response.json(): JSON オブジェクトを取得します。
  • response.blob(): バイナリ Blob オブジェクトを取得します。
  • response.formData(): FormData フォーム オブジェクトを取得します。
  • response.arrayBuffer(): バイナリ ArrayBuffer オブジェクトを取得します。

上記の 5 つの読み取りメソッドはすべて非同期であり、Promise オブジェクトを返します。サーバーから返される完全なデータを取得するには、非同期操作が終了するまで待つ必要があります。

response.text()

response.text() を使用すると、HTML ファイルなどのテキスト データを取得できます。

const 応答 = await fetch('/users.html');
const body = 応答を待つ.text();
document.body.innerHTML = 本文

response.json()

response.json() は主にサーバーから返された JSON データを取得するために使用されます。例は前に示しました。

response.formData()

response.formData() は主に Service Worker で使用され、ユーザーが送信したフォームをインターセプトし、一部のデータを変更してからサーバーに送信します。

response.blob()

response.blob() はバイナリ ファイルを取得するために使用されます。

const 応答 = await fetch('flower.jpg');
const myBlob = 応答を待ちます。blob();
const objectURL = URL.createObjectURL(myBlob);

const myImage = document.querySelector('img');
myImage.src = オブジェクトURL;

上記の例では、画像ファイル flower.jpg を読み込み、Web ページに表示します。

response.arrayBuffer()

response.arrayBuffer() は主にストリーミング メディア ファイルを取得するために使用されます。

const audioCtx = 新しい window.AudioContext();
const ソース = audioCtx.createBufferSource();

const 応答 = await fetch('song.ogg');
const バッファ = 応答を待ちます。arrayBuffer();

const decodeData = await audioCtx.decodeAudioData(buffer);
ソース.バッファ = バッファ;
ソース.connect(audioCtx.destination);
ソースループ = true;

上記の例は、response.arrayBuffer() がオーディオ ファイル song.ogg を取得し、それをオンラインで再生する例です。

Response.clone()

Stream オブジェクトは 1 回しか読み取ることができず、読み取った後は失われます。これは、前のセクションの 5 つの読み取り方法のうち 1 つだけを使用でき、それ以外の場合はエラーが報告されることを意味します。

let text = 応答を待ちます。text();
let json = await response.json(); // エラーを報告する

上記の例では、最初に response.text() を使用し、次にストリームの読み取りを終了します。後で「response.json()」を呼び出すと、読み取るコンテンツがないため、エラーが報告されます。

Response オブジェクトは、複数の読み取りを可能にするために Response オブジェクトのコピーを作成するための Response.clone() メソッドを提供します。

const response1 = await fetch('flowers.jpg');
const 応答 2 = 応答 1.clone();

const myBlob1 = 応答 1.blob() を待ちます。
const myBlob2 = 応答 2.blob() を待ちます。

image1.src = URL.createObjectURL(myBlob1);
image2.src = URL.createObjectURL(myBlob2);

上記の例では、response.clone() は Response オブジェクトをコピーし、同じイメージを 2 回読み取ります。

Response オブジェクトには、Response 結果を指定された URL にリダイレクトするために使用される Response.redirect() メソッドもあります。このメソッドは通常 Service Worker でのみ使用されるため、ここでは紹介しません。

Response.body プロパティ

Response.body プロパティは、Response オブジェクトによって公開される基礎となるインターフェイスであり、ユーザー操作のために ReadableStream オブジェクトを返します。

これはコンテンツをチャンクで読み取るために使用でき、アプリケーションの 1 つはダウンロードの進行状況を表示することです。

const 応答 = await fetch('flower.jpg');
const リーダー = 応答.body.getReader();

while(true) {
  const {done, value} = await Reader.read();

  if (完了) {
    壊す;
  }

  console.log(`${value.length} バイトを受信しました`)
}

上の例では、response.body.getReader() メソッドはイテレータを返します。このトラバーサの read() メソッドは、毎回、今回読み取られたコンテンツ ブロックを表すオブジェクトを返します。

このオブジェクトの done プロパティはブール値で、読み取られたかどうかを判断するために使用されます。 value プロパティはコンテンツ ブロックの内容を表す arrayBuffer 配列であり、value.length プロパティは現在のブロックのサイズ。

fetch() の 2 番目のパラメータ: カスタマイズされた HTTP リクエスト

fetch() の最初のパラメータは URL で、2 番目のパラメータは、発行される HTTP リクエストをカスタマイズするための設定オブジェクトとして受け取ることもできます。

fetch(url, optionObj)

上記のコマンドの optionObj は 2 番目のパラメータです。

HTTPリクエストのメソッド、ヘッダー、データ本体はすべてこのオブジェクトに設定されます。以下にいくつかの例を示します。

(1)POSTリクエスト

const 応答 = await fetch(url, {
  メソッド: 'POST'、
  ヘッダー: {
    "コンテンツタイプ": "application/x-www-form-urlencoded; charset=UTF-8",
  }、
  本文: 'foo=bar&lorem=ipsum',
});

const json = 応答を待ちます.json();

上記の例では、構成オブジェクトで 3 つのプロパティが使用されています。

  • method: HTTP リクエストメソッド、POSTDELETEPUT はすべてこの属性に設定されます。
  • headers: HTTP リクエストのヘッダーをカスタマイズするために使用されるオブジェクト。
  • body: POST リクエストのデータ本体。

Content-LengthCookieHost など、一部のヘッダーは headers 属性を通じて設定できないことに注意してください。これらはブラウザによって自動的に生成され、変更することはできません。

(2)JSONデータを送信

const user = { 名前: 'ジョン'、姓: 'スミス' };
const 応答 = await fetch('/article/fetch/post/user', {
  メソッド: 'POST'、
  ヘッダー: {
   'コンテンツタイプ': 'application/json;charset=utf-8'
  }、
  本文: JSON.stringify(ユーザー)
});

上の例では、ヘッダー Content-Type'application/json;charset=utf-8' に設定する必要があります。デフォルトではプレーンテキストが送信されるため、「Content-Type」のデフォルト値は「text/plain;charset=UTF-8」です。

(3) フォームを送信してください

const form = document.querySelector('form');

const 応答 = await fetch('/users', {
  メソッド: 'POST'、
  本文: 新しい FormData(フォーム)
})

(4)ファイルのアップロード

フォーム内にファイルセレクターがある場合は、アップロードしたファイルをフォーム全体に含めて一括送信することができます。

別の方法は、スクリプトを使用してファイルを追加し、フォームを作成し、アップロードすることです。以下の例を参照してください。

const input = document.querySelector('input[type="file"]');

const データ = 新しい FormData();
data.append('file', input.files[0]);
data.append('ユーザー', 'foo');

fetch('/アバター', {
  メソッド: 'POST'、
  本体:データ
});

バイナリ ファイルをアップロードする場合、ヘッダーの Content-Type を変更する必要はなく、ブラウザによって自動的に設定されます。

(5) バイナリデータを直接アップロード

fetch() は、Blob または arrayBuffer データを body 属性に配置して、バイナリ データを直接アップロードすることもできます。

let blob = await 新しい Promise(resolve =>
  CanvasElem.toBlob(解決, 'image/png')
);

let response = await fetch('/article/fetch/post/image', {
  メソッド: 'POST'、
  ボディ: ブロブ
});

fetch() 設定オブジェクトの完全な API

fetch() の 2 番目のパラメータの完全な API は次のとおりです。

const 応答 = fetch(url, {
  メソッド: "GET"、
  ヘッダー: {
    "Content-Type": "text/plain;charset=UTF-8"
  }、
  本体: 未定義、
  リファラー: "about:client",
  ReferrerPolicy: "ダウングレード時はリファラーなし",
  モード: "cors"、
  資格情報: "同じオリジン"、
  キャッシュ: "デフォルト",
  リダイレクト: "フォロー",
  誠実さ: ""、
  キープアライブ: false、
  信号: 未定義
});

fetch() リクエストの最下層は、Request() オブジェクト のインターフェイスとパラメータを使用します。全く同じなので、上記の API も Request() の API です。

これらの属性のうち、headersbody、および method については以前に例を示しました。次に、その他の属性について説明します。

キャッシュ

cache 属性は、キャッシュの処理方法を指定します。可能な値は次のとおりです。

  • default: デフォルト値。最初にキャッシュ内で一致するリクエストを検索します。
  • no-store: リモート サーバーに直接リクエストし、キャッシュを更新しません。
  • reload: リモートサーバーに直接リクエストしてキャッシュを更新します。
  • no-cache: サーバー リソースとローカル キャッシュを比較し、新しいバージョンがある場合にのみサーバー リソースを使用し、それ以外の場合はキャッシュを使用します。
  • force-cache: キャッシュの優先順位。キャッシュがない場合にのみリモート サーバーが要求されます。
  • only-if-cached: キャッシュのみをチェックします。キャッシュに存在しない場合は、504 エラーが返されます。

モード

mode 属性は、要求されたモードを指定します。可能な値は次のとおりです。

  • cors: デフォルト値。クロスオリジンリクエストを許可します。
  • same-origin: 同じオリジンからのリクエストのみが許可されます。
  • no-cors: リクエスト メソッドは GET、POST、HEAD に制限されており、限られた数の単純なヘッダーのみを使用できます。クロスオリジンの複雑なヘッダーは追加できません。これは、フォームと <script> を送信するのと同じです。 スクリプトの読み込み 、 <img> 画像およびその他の従来のクロスオリジン リクエスト メソッドを読み込みます。

資格

「credentials」属性は、Cookie を送信するかどうかを指定します。可能な値は次のとおりです。

  • same-origin: デフォルト値。Cookie は同一オリジンリクエストを作成したときに送信され、クロスオリジンリクエストが作成されたときは送信されません。
  • include: Cookie は、オリジンリクエストまたはクロスオリジンリクエストに関係なく、常に送信されます。
  • 省略: 決して送信しません。

オリジンリクエスト間で Cookie を送信するには、credentials 属性を include に設定する必要があります。

fetch('http://another.com', {
  資格情報: "含む"
});

信号

signal 属性は、fetch() リクエストをキャンセルするための AbortSignal インスタンスを指定します。詳細については、次のセクションを参照してください。

キープアライブ

「keepalive」属性は、バックグラウンドで接続を維持し、ページがアンロードされたときにデータを送信し続けるようにブラウザに指示するために使用されます。

典型的なシナリオは、ユーザーが Web ページを離れるときに、スクリプトがユーザーの行動に関する統計情報をサーバーに送信するというものです。このとき、keepalive属性を使用しないと、ブラウザがページをアンロードしてしまい、データが送信されない可能性があります。

window.onunload = function() {
  fetch('/analytics', {
    メソッド: 'POST'、
    ヘッダー: {
      'コンテンツタイプ': 'アプリケーション/json'
    }、
    本文: JSON.stringify({
      一部: 「データ」
    })、
    キープアライブ: true
  });
};

リダイレクト

「redirect」属性は、HTTP リダイレクトの処理方法を指定します。可能な値は次のとおりです。

  • follow: デフォルト値、fetch() は HTTP ジャンプに従います。
  • error: ジャンプが発生すると、fetch() はエラーを報告します。
  • manual: fetch() は HTTP ジャンプに従いませんが、response.url 属性は新しい URL を指し、response.redirected 属性は true になり、開発者が決定します。後はジャンプでどう対処するか。

誠実さ

「integrity」属性は、HTTP 応答によって返されたデータがこの事前設定されたハッシュ値と等しいかどうかをチェックするために使用されるハッシュ値を指定します。

たとえば、ファイルをダウンロードするときは、ファイルの SHA-256 ハッシュが一致するかどうかをチェックして、ファイルが改ざんされていないことを確認します。

fetch('http://site.com/file', {
  整合性: 'sha256-abcdef'
});

紹介者

referrer 属性は、fetch() リクエストの referr ヘッダーを設定するために使用されます。

この属性は任意の文字列にすることも、空の文字列に設定することもできます (つまり、「referer」ヘッダーは送信されません)。

fetch('/ページ', {
  参照者: ''
});

参照者ポリシー

referrerPolicy 属性は、Referer ヘッダーのルールを設定するために使用されます。可能な値は次のとおりです。

  • no-referrer-when-downgrade: デフォルト値。HTTPS ページから HTTP リソースを要求する場合を除き、常に Referer ヘッダーを送信します。
  • no-referrer: Referer ヘッダーを送信しません。
  • origin: Referer ヘッダーにはドメイン名のみが含まれ、フルパスは含まれません。
  • origin-when-cross-origin: 同一オリジンリクエストの Referer ヘッダーには完全なパスが含まれ、クロスオリジンリクエストにはドメイン名のみが含まれます。
  • same-origin: Referer はクロスオリジンリクエストには送信されませんが、同一オリジンリクエストには送信されます。
  • strict-origin: Referer ヘッダーにはドメイン名のみが含まれており、HTTPS ページが HTTP リソースを要求するときに Referer ヘッダーは送信されません。
  • strict-origin-when-cross-origin: Referer ヘッダーには、同一オリジン リクエストの場合はフル パスが含まれ、クロスオリジン リクエストの場合はドメイン名のみが含まれます。このヘッダーは送信されません。 HTTPS ページは HTTP リソースを要求します。
  • unsafe-url: 何があっても常に Referer ヘッダーを送信します。

fetch() リクエストをキャンセルします

fetch() リクエスト送信後、途中でキャンセルしたい場合は、AbortController オブジェクトを使用する必要があります。

let コントローラー = new AbortController();
シグナル = コントローラー.シグナル;

fetch(url, {
  信号: コントローラー.信号
});

signal.addEventListener('中止',
  () => console.log('中止!')
);

controller.abort(); // キャンセル

console.log(signal.aborted); // true

上の例では、まず新しい AbortController インスタンスを作成し、次に fetch() リクエストを送信します。構成オブジェクトの signal プロパティは、AbortController インスタンスによって送信されたシグナル controller.signal を受信するように指定する必要があります。

controller.abort() メソッドは、キャンセルを通知するために使用されます。このとき、「abort」イベントがトリガーされます。このイベントは監視でき、「controller.signal.aborted」プロパティを使用してキャンセル信号が送信されたかどうかを確認することもできます。

以下は 1 秒後にリクエストを自動的にキャンセルする例です。

let コントローラー = new AbortController();
setTimeout(() =>controller.abort(), 1000);

試す {
  let response = await fetch('/long-operation', {
    信号: コントローラー.信号
  });
キャッチ(エラー) {
  if (err.name == 'AbortError') {
    console.log('中止されました!');
  } それ以外 {
    エラーをスローします。
  }
}

参考リンク


作者: wangdoc

アドレス: https://wangdoc.com/

ライセンス: クリエイティブ・コモンズ 3.0