前回XMLHttpRequestを用いた非同期処理について解説をしましたが、今回はFetch APIを使用した非同期処理について解説します。元々XMLHttpRequestが非同期通信の主格として存在感を発揮していましたが、その代替としてfetchが登場しました。

XMLHttpRequestの解説記事 : /javascript/ajax-request

fetchとXMLHttpRequestではどのような違いがあるのでしょうか?

fetchとXMLHttpRequestの違い

長々と文章で解説しても仕方がないので、リクエストを送信する場合のサンプルコードを解説します。

XMLHttpRequest

const req = new XMLHttpRequest();
req.open('GET', url);
req.send();

fetch

fetch(url);

【解説】

XMLHttpRequestは、XMLHttpRequestの呼び出し => 通信設定 => 通信開始というフローを踏まなければならない一方で、Fetch APIはfetch(url)という記述のみでリクエストを送信することができます。しかしfetchの強みはリクエストを送信し、後続処理をPromiseチェーンを用いた記述で処理できるということにあります。

Promiseについては下記の記事で解説した通り、処理をthen(), catch()でチェーンのようにつないで、処理結果の状態によって後続処理をコントロールできる仕組みです。

Promiseについての解説記事 : /javascript/asynchronous-processing

非同期処理にかかわらず、全てのプログラムの実行結果は「成功」 or  「失敗」のどちらかになります。fetch()では成功した場合はthen()で繋いだ後続処理、失敗した場合はcatch()で繋いだ後続処理を実行し、それらを一連のコードで示すことができます。

Fetch APIの使い方

リクエストの送信とレスポンスの処理

ここではサンプルコードを用いてFetch APIでリクエストの送信とレスポンスの受け取りを行います。

■ Github APIアクセスして、ユーザー情報を取得するサンプルコード

fetch('https://api.github.com/users/${user_id}')
.then((res) => res.json())
.then((json) => console.log(json))
.catch((error) => console.log(error))

【解説】

fetchではPromiseチェーンを使って、上記のようにリクエストとレスポンスを記述します。

まず、最初のレスポンスがresに格納されていますが、オブジェクトの中身を取り出す処理をthen()で繋いだ後続処理に記述します。res.json()でJSONを取り出した後にコンソールに表示させています。そしてエラーハンドリング処理としてcatch()にエラー時の処理を記述します。

上記のコードの${user_id}に任意の値を当てて非同期通信をしてみてください。

リクエストが成功したかを判定する

送信したリクエストが成功したかを判定する場合は、レスポンス(res)のokプロパティで認識することができます。

fetchから返されたPromiseオブジェクトは応答が400, 500番台の場合でも、レスポンスを返す特徴を持つため、okプロパティを判定に使用します。

okプロパティはHTTPステータスコードが200番台(成功)であればtrueを返し、400, 500番台の場合はfalseを返します。レスポンスが正常でないケースとして、プログラム以外にもネットワーク環境が原因で正常に処理ができない場合もあるので、レスポンスのHTTPステータスコードを判定条件にして適切にコードを書く必要があります。

■ okプロパティを使用したサンプルコード

fetch('https://api.github.com/users/${user_id}')
.then((res) => {
  // okステータスで判定
 if(!res.ok) {
   console.log('正常にリクエストを処理できませんでした。');
 }
 return res.json()
})
.then((json) => console.log(json))
.catch((error) => console.log(error));

レスポンスの取得データの形式を指定する

fetchのレスポンスのPromiseオブジェクトの本文にアクセスする際に、追加メソッドを記述することで任意のデータ形式で取得することができます。上記のサンプルコードではJSON形式を指定してデータを取り出しましたが、そのほかの追加メソッドについても解説します。

res.json() : レスポンスをJSONオブジェクトとしてパースする

res.text() : レスポンスをテキストとして返す

res.formData() : FormDataオブジェクトとして返す

res.blob() : Blobとしてレスポンスを返す

res.arrayBuffer() : ArrayBufferとしてレスポンスを返す

取得したい形式に応じて追加メソッドを指定してください。

データの送信

非同期処理を実装する際に、GETメソッドでデータを受信する以外にPOSTを使用して、データを送信する場合もあります。特にシステム開発の場面では、ユーザーの操作結果や入力情報をサーバーサイドに送信し、データベースにデータを保存・取得する処理が行われています。

筆者はJavaScriptとCakePHPを使用してシステム開発を行っているので、非同期処理でPOSTを使用してデータを送信・サーバーサイドで処理する流れを下記で解説します。

・fetchメソッドのURLにcakePHPのコントローラーを指定
・fetch()の引数でメソッドをPOSTに指定
・FormDataをfetch()の引数bodyに指定して送信
・CakePHPのコントローラーでデータを受信
・CakePHPのモデルにデータベースの処理を渡す
・モデルでの処理が完了したらコントローラーに処理結果をreturnする
・コントローラーからフロントに処理結果(データ, 値など)をreturnする
・fetchのthen()で受け取ったデータを処理

■ POSTでデータを送信するサンプルコード

const url = サーバーサイドのコントローラー;
const formData = サーバーサイドに送信するFormDataオブジェクト;

fetch(url, {
 method: 'POST',
 body: formData
})
.then((res) => {
 if(!res.ok) {
   return false;
 }
 return res.text()
})
.then((text) => console.log(text))
.catch((error) => console.log(error))

fetch()に指定する引数について

第一引数にアクセス先(URL)、第二引数にリクエストに適応したい設定のオブジェクトを指定します。

fetch(url, {
method: 'POST',
body: formData
})

以上、fetch()の使用方法について解説しました。

参考 : https://developer.mozilla.org/ja/docs/Web/API/Fetch_API

カテゴリー: JavaScript