非同期通信 fetch
fetch オブジェクトは、XMLHttpRequest(XHR) オブジェクトに代わる、サーバーと対話するためのAPIです。
fetch はプロミス値を返しますので、XMLHttpRequest に比べて、簡略化されて可読性の良いスクリプトを書くことができます。
この記事では、演習用のJSONデータとして MDN が用意しているデータを利用します。
https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json
fetch を使ってサーバーからデータを取り込む方法を説明するのが目的なので、データの中身はあまり気にしないでください。
fetch() メソッド
fetch() メソッドの基本構文
let promise = fetch( URL , {オプション} ) ;
非同期関数を使って、サーバーからデータを取得
では、サーバーからデータを取得してみましょう。
非同期関数 ( async / await ) を使って、データを取得してみます。
async function getData() { const response = await fetch('https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json') ; const resData = await response.json() ; console.log( 'response' , response ) ; console.log( 'resData' , resData ) ; console.log( resData.squadName ) ; // Super Hero Squad } getData() ; /* response Response {type: 'cors', url: 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json', redirected: false, status: 200, ok: true, …} resData {squadName: 'Super Hero Squad', homeTown: 'Metro City', formed: 2016, secretBase: 'Super tower', active: true, …} */
fetch() メソッドは Response オブジェクトを返します。
fetch() メソッドによりサーバーへリクエストが送られると、すぐにプロミスが “pending” で返されます。その後サーバーがヘッダを受け取り通信状態を応答すると、Response オブジェクトで resolve します。Response オブジェクトには通信状態を示す、status (HTTPステータスコード) / ok (HTTPステータスコードが200~299の時 true)などが返されます。
但し、この時点では、サーバーとの通信(リクエスト)が確立されただけで、実際のデータは取得されていません。
Response オブジェクトの json() メソッドにより、JSON として解釈した結果で resolve するプロミスを返します。Responseオブジェクトのストリームを取得して、データを読み取り後JSONとして解釈し、JavaScriptのオブジェクトで resolve します。
エラー処理を入れてみます。
async function postData() { try { const response = await fetch('https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json') ; if ( !response.ok ) { throw 'FETCH ERROR! HTTP Status:' + response.status ; } const resData = await response.json() ; console.log( response ) ; console.log( resData ) ; } catch( e ) { // *** console.error(e) ; } } postData() ;
スクリプトでは Response オブジェクトの ok プロパティでエラー処理の判断をしていますが、status プロパティを使えばもっと詳しくエラー処理をおこなうことも可能です。
プロミスチェーンで書く
非同期関数を使わないスクリプトです。
fetch('https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.jsonX') .then( ( response ) => { console.log( response ) ; return response.json() ; }).then( ( resData ) => { console.log( resData ) ; console.log( resData.squadName ) ; // Super Hero Squad }).catch( ( e ) => { console.error( e ) ; }) ;
JSONデータ取得関数にしてみる。
少しだけ汎用性をもたせて、URLとパラメータを渡すとJSON形式でデータが取得できる関数を作成します。
今回は渡したパラメータが、ホスト側で利用されることはありませんが、スクリプトの例としてパラメータを渡しています。
リクエスト先の URL が変わっていますが、POSTする場合はCROS(Cross-Origin Resource Sharing)でエラーとなりますので、ローカル環境にJSONを作成しています。
// 汎用JSON取得関数 async function postData( argURL , argData ) { try { const response = await fetch( argURL , { method: 'POST' , // メソッドPOST headers: { 'Content-Type': 'application/json' }, body: JSON.stringify( argData ), // JSONでパラメータを渡します。型は "Content-Type" ヘッダーと一致させる必要があります } ) ; if ( !response.ok ) { // fetchのエラーチェック throw 'FETCH ERROR! HTTP Status:' + response.status ; // fetchでエラーがあればエラーを投げる } const resData = await response.json() ; // レスポンスデータのの取得 return { // データの取得状態(true)と取得したJSONデータを返します。 status: true , retData: resData , } ; } catch( e ) { // エラー処理 return { // データの取得状態(false)とエラー内容を返します。 status: false , retData: e , } ; } } // プロフィール表示関数 async function getProfile( argName ) { data = { name : argName } ; try { const res = await postData( 'http://localhost/testsrc/files/superheroes.json' , data) ; if ( !res.status ) { // データの取得状態のチェック throw res.retData ; // 正常に取得できなかったらエラーを投げてcatch()で処理する。 } // データが正常に取得できた処理 const retData = res.retData ; console.log( argName + ' ' + retData.squadName ) ; // Heroes Super Hero Squad } catch( e ) { // エラーの処理 console.error(e) ; } } getProfile( 'Heroes' ) ;
汎用JSON取得非同期関数 postData は、データ取得URL とパラメータ用データを渡すと、取得状態とデータを受け取ることができます。プロフィール表示関数 getProfileは、この汎用JSON取得非同期関数 postData を使って取得したデータを表示しています。
JSON以外のオブジェクトの取得
今回の例では、JSON データを取得してますが、Response オブジェクトには、それ以外にもメソッドが用意されています。
- Response.arrayBuffer()
レスポンスの本文を表す ArrayBuffer で解決するプロミスを返します。 - Response.blob()
レスポンスの本文を表す Blob で解決するプロミスを返します。 - Response.clone()
Response オブジェクトの複製を生成します。 - Response.error()
ネットワークエラーに関連した新しい Response オブジェクトを返します。 - Response.formData()
レスポンスの本文を表す FormData で解決するプロミスを返します。 - Response.json()
レスポンスの本文のテキストを JSON として解釈した結果で解決するプロミスを返します。 - Response.redirect()
異なる URL で新しい response を生成します。 - Response.text()
レスポンスの本文のテキスト表現で解決するプロミスを返します。
参考リンク
MDN 開発者向けのウェブ技術 > WindowOrWorkerGlobalScope.fetch()
MDN 開発者向けのウェブ技術 > Fetch API
MDN 開発者向けのウェブ技術 > Response
MDN 開発者向けのウェブ技術 > Response.json()
MDN 開発者向けのウェブ技術 > Fetch の使用
ウェブ開発を学ぶ > JavaScript > クライアントサイドWebAPI > サーバからのデータ取得
MDN 開発者向けのウェブ技術 > HTTP > オリジン間リソース共有 (CORS)
MDN 開発者向けのウェブ技術 > JavaScript「再」入門