fetch() の概要

fetch() を使用すると、XMLHttpRequest(XHR)と同様のネットワーク リクエストを行うことができます。主な違いは、Fetch API では Promise を使用する点です。Promise には、XMLHttpRequest API の複雑なコールバックを回避するためのシンプルな API が用意されています。

対応ブラウザ

  • 42
  • 14
  • 39
  • 10.1

ソース

Promise を初めて使用する場合は、JavaScript Promise の概要をご覧ください。

基本的な取得リクエスト

以下に、XMLHttpRequest で実装し、次に fetch で実装した例を示します。URL をリクエストしてレスポンスを取得し JSON として解析する必要があります

XMLHttpRequest

XMLHttpRequest には、成功ケースとエラーケースを処理するための 2 つのリスナーと、open()send() の呼び出しが必要です。MDN ドキュメントの例

function reqListener() {
    var data = JSON.parse(this.responseText);
    console.log(data);
}

function reqError(err) {
    console.log('Fetch Error :-S', err);
}

var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();

フェッチ

取得リクエストは次のようになります。

fetch('./api/some.json')
  .then(
  function(response) {
    if (response.status !== 200) {
      console.log('Looks like there was a problem. Status Code: ' +
        response.status);
      return;
    }

    // Examine the text in the response
    response.json().then(function(data) {
      console.log(data);
    });
  }
  )
  .catch(function(err) {
    console.log('Fetch Error :-S', err);
  });

fetch() リクエストで 1 回の呼び出しだけで、XHR の例と同じ処理を行えます。レスポンスを処理するには、まずレスポンス ステータスが 200 であることを確認してから、レスポンスを JSON として解析します。fetch() リクエストに対するレスポンスは Stream オブジェクトです。つまり、json() メソッドを呼び出すと、Promise が返されます。ストリームは非同期的に行われます。

レスポンス メタデータ

前の例では、Response オブジェクトのステータスと、レスポンスを JSON として解析する方法を示しました。ヘッダーなど、アクセスする必要があるその他のメタデータの処理方法は次のとおりです。

fetch('users.json').then(function(response) {
    console.log(response.headers.get('Content-Type'));
    console.log(response.headers.get('Date'));

    console.log(response.status);
    console.log(response.statusText);
    console.log(response.type);
    console.log(response.url);
});

レスポンス タイプ

フェッチ リクエストを行うと、レスポンスに「basic」、「cors」、「opaque」の response.type が返されます。これらの types はリソースの取得元を示し、これらを使用してレスポンス オブジェクトの処理方法を決定できます。

ブラウザが同じ生成元のリソースをリクエストすると、レスポンスは basic タイプになり、レスポンスから表示できる内容が制限されます。

別のオリジンのリソースに対するリクエストが行われ、そのオリジンが CORs ヘッダーを返した場合、タイプは cors です。cors レスポンスは basic レスポンスに似ていますが、表示できるヘッダーは Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma に制限されます。

opaque レスポンスの送信元が CORS ヘッダーを返さない別のオリジンから返された。不透明なレスポンスでは、返されたデータの読み取りやリクエストのステータスの表示ができません。つまり、リクエストが成功したかどうかを確認することはできません。

特定のリクエスト タイプのみが解決されるように、取得リクエストのモードを定義できます。設定可能なモードは次のとおりです。

  • same-origin は、同じオリジンのアセットに対するリクエストに対してのみ成功し、他のすべてのリクエストを拒否します。
  • cors は、同じオリジンと適切な COR ヘッダーを返す他のオリジンのアセットに対するリクエストを許可します。
  • cors-with-forced-preflight は、リクエストを行う前にプリフライト チェックを実行します。
  • no-cors は、CORS ヘッダーがなく opaque レスポンスを返す他のオリジンにリクエストを行うためのものですが、前述のように、現時点ではウィンドウのグローバル スコープではこれを行えません。

モードを定義するには、fetch リクエストの 2 番目のパラメータとしてオプション オブジェクトを追加し、そのオブジェクトでモードを定義します。

fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
    .then(function(response) {
    return response.text();
    })
    .then(function(text) {
    console.log('Request successful', text);
    })
    .catch(function(error) {
    log('Request failed', error)
    });

Promise チェーン

Promise の優れた機能の一つは、それらを連鎖させることです。fetch() の場合、これによりフェッチ リクエスト間でロジックを共有できます。

JSON API を使用している場合は、ステータスを確認し、各レスポンスの JSON を解析する必要があります。Promise を返す個別の関数でステータスと JSON 解析を定義し、フェッチ リクエストを使用して最終データとエラーケースのみを処理することで、コードを簡素化できます。

function status(response) {
    if (response.status >= 200 && response.status < 300) {
    return Promise.resolve(response)
    } else {
    return Promise.reject(new Error(response.statusText))
    }
}

function json(response) {
    return response.json()
}

fetch('users.json')
    .then(status)
    .then(json)
    .then(function(data) {
    console.log('Request succeeded with JSON response', data);
    }).catch(function(error) {
    console.log('Request failed', error);
    });

この例では、response.status を確認し、解決済みの Promise を Promise.resolve() として、または拒否された Promise を Promise.reject() として返す status 関数を定義しています。これは、fetch() チェーンで最初に呼び出されるメソッドです。

Promise が解決されると、スクリプトは json() メソッドを呼び出します。このメソッドは response.json() 呼び出しから 2 つ目の Promise を返し、解析された JSON を含むオブジェクトを作成します。解析が失敗すると、Promise は拒否され、 catch ステートメントが実行されます。

この構造を使用すると、すべてのフェッチ リクエストでロジックを共有できるため、コードの保守、読み取り、テストが容易になります。

POST リクエスト

ウェブアプリは、POST メソッドを使用して API を呼び出し、リクエストの本文にいくつかのパラメータを含めることが必要になる場合があります。これを行うには、fetch() オプションで method パラメータと body パラメータを設定します。

fetch(url, {
    method: 'post',
    headers: {
        "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
    },
    body: 'foo=bar&lorem=ipsum'
    })
    .then(json)
    .then(function (data) {
    console.log('Request succeeded with JSON response', data);
    })
    .catch(function (error) {
    console.log('Request failed', error);
    });

取得リクエストで認証情報を送信する

Cookie などの認証情報を使用して取得リクエストを行うには、リクエストの credentials 値を "include" に設定します。

fetch(url, {
    credentials: 'include'
})