[フロントエンド] fetchを用いたAjax通信を行う
こんにちは、@yoheiMuneです。
XMLHttpRequestに変わる次のAjax仕様としてfetchが策定されていますが、今日はそれを扱ったAjax通信をブログに書きたいと思います。
また、fetchはPromiseを使った実装となります。Promiseについては「[Javascript] Promise/A+仕様を、チュートリアル形式で詳しく解説します」をご参照ください。
https://github.github.io/fetch/#request-body
https://github.com/github/fetch
https://github.github.io/fetch/
Fetch 概説 - Web API インターフェイス | MDN
最後になりますが本ブログでは、フロントエンド・Go言語・Node.js・Python・Linux・開発関連・Swift・Java・機械学習など雑多に情報発信をしていきます。自分の第2の脳にすべく、情報をブログに貯めています。気になった方は、本ブログのRSSやTwitterをフォローして頂けると幸いです ^ ^。
最後までご覧頂きましてありがとうございました!
XMLHttpRequestに変わる次のAjax仕様としてfetchが策定されていますが、今日はそれを扱ったAjax通信をブログに書きたいと思います。
目次
fetchとは
fetchとはwhatwgで策定されている、フロントエンドJavaScriptの次世代の非同期通信の規格で、XMLHttpRequestに取って代わるものです。例えば以下のような使い方ができます。fetch('/user/1').then(response => { console.log(response.status); // 200 return response.json(); }).then(json => { console.log('json:', json); // json : { name : 'Yohei' } });XMLHttpRequestに比べてシンプルです。現時点でもfetch | Githubで提供されているポリフィルを用いて利用可能ですので、今日はそれを使ってみたいと思います。
また、fetchはPromiseを使った実装となります。Promiseについては「[Javascript] Promise/A+仕様を、チュートリアル形式で詳しく解説します」をご参照ください。
fetchのポリフィルの導入
fetch | Githubで公開されているfetchのポリフィルは、bowser
またはnpm
でインストール可能です。例えばBowerを使ってインストールするには以下のように行います。$ bower init $ bower install --save fetchこれでインストールしたものをHTMLから読み込めばOKです。今回は以下のようなHTMLを使います。
<html> <body> <script type="text/javascript" src="./bower_components/fetch/fetch.js"></script> <script type="text/javascript" src="./fetch-sample.js"></script> </body> </html>
サンプルコード
今回のサンプルコードはこちらおきました。サーバー側はNodeのExpressを利用していて、起動は以下のように行います。$ bower install $ npm install $ node server.js # => http://localhost:3000
fetchのいろいろな使い方
さてここから本題ですが、fetchについて主だった使い方を書きたいと思います。基本的な使い方
以下のような形式で利用することができます。fetch(url, options).then(function(response) { // handle HTTP response }, function(error) { // handle network error });
url
とoptions
を指定してfetchを呼び出し、結果はPromiseベースで受け取ります。レスポンスには例えば以下のようなものが含まれます。fetch(url, options).then(function(response) { // ステータスコード console.log(response.status); // 200 // ステータス(文字列) console.log(response.statusText); // 'OK' // レスポンスヘッダー console.log(response.headers); // {} : オブジェクト形式で取得可能 // URL console.log(response.url); // http://localhost:3000/sample });具体的な使い方は以降で見ていきたいと思います。
結果をテキストファイルやHTMLで受け取る
レスポンス結果をテキストベースで受け取る場合には、response.text()
で取り出します。fetch('/text').then(response => { // textやhtmlなどの文字列で値を受け取る場合は、textメソッドを呼びます. // このメソッドはPromiseを返却します。 return response.text(); }).then(text => { // Promiseが解決されたら値が取得できます. console.log('text:', text); // text: 鈴木さん });
結果をJSONで受け取る
レスポンスデータをJSONで受け取る場合には、response.json()
を使います。fetch('/json').then(response => { // JSONで値を受け取る場合は、jsonメソッドを使います。 // このメソッドはPromiseを返却します。 return response.json(); }).then(jsonData => { console.log('jsonData:', jsonData); // jsonData: Object {name: "鈴木さん"} });ここでは内部的に
JSON.parse
が実行されます。例えばレスポンスボディが空の場合にはエラーになるので、少しだけ注意が必要です。400や500エラーもresolvedされる
fetchの特徴として、HTTPステータスが400系や500系エラーでも、処理はエラーにならず、Promiseはresolvedになります。// 400や500系のステータスでも、resolvedで処理される. fetch('/400').then(response => { console.log('status: ', response.status); }); fetch('/500').then(response => { console.log('status: ', response.status); });ステータスコードでの処理振り分けが必要な場合には、それぞれ個別に実装します。
ネットワークエラーなどでは失敗する
ネットワークエラーなどの場合にだけ、fetchのPromiseはrejectedになります。サンプルコードの場合には、画面を表示した後にNodeサーバーを落とした状態でfetchすると再現できます。// ネットワークエラーなどの時だけ失敗する。(ローカルサーバー落とすとかしてテスト) fetch('/NETWORKERROR').then(res => { console.log('resolved'); // resolvedにはならない. }).catch(err => { console.log('rejected:', err); // rejected: TypeError: Failed to fetch });なお、パス間違い404になった場合はこのエラーにはならずresolvedされますので、注意です。fetchがrejectedになるのは、フロント的にはもうどうすることもできないfatal状態といった感じでしょうか。
GETパラメータを付与する
GETパラメータはURLに付与して送ります。// URLにパラメータをつけて送ります. fetch('/get_with_params?id=1&name=yohei') .then(response => response.text()) .then(text => console.log(text)); // params.id=1, params.name=yoheiまた、URLSearchParamsを使ってURLクエリを作成することもできます。
// GETの場合のパラメータの送り方①:URLSearchParamsを利用 // https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams const params = new URLSearchParams(); params.set('id', 2); params.set('name', 'munerin'); fetch('/get_with_params?' + params.toString()) .then(response => response.text()) .then(text => console.log(text));
POSTデータを送る(JSON形式)
POSTでデータを送る場合には、options.body
に値を設定します。またContent-Type
ヘッダーを指定します。// POSTで送る場合(JSON形式) fetch('post_with_params', { method : 'POST', body : JSON.stringify({ id : 3, name : 'matsu' }), // 文字列で指定する headers : new Headers({ "Content-type" : "application/json" }) }).then(response => response.text()) .then(text => console.log(text)); // params.id=3, params.name=matsuなお、Bodyに指定する値によって、以下の値がデフォルト値として
Content-Type
に指定されます。クラス | Content-Typeのデフォルト値 |
---|---|
String | text/plain;charset=UTF-8 |
URLSearchParams | application/x-www-form-urlencoded;charset=UTF-8 |
FormData | multipart/form-data |
Blob | inherited from the blob.type property |
POSTデータを送る(Form形式)
Form形式でも送ることができます。// POSTで送る場合(FormData形式) fetch('post_with_params', { method : 'POST', body : 'id=4&name=shinji', headers : new Headers({'Content-type' : 'application/x-www-form-urlencoded' }) }).then(response => response.text()) .then(text => console.log(text)); // params.id=4, params.name=shinji
optionsで指定できる値
fetch
の第2引数に指定するoptions
には以下の項目が指定できます。- method (String) - HTTPメソッド。初期値は
GET
- body (String, body types) - レスポンスボディの種類
- headers (Object, Headers) - HTTPヘッダー。初期値は
{}
- credentials (String) - 認証モードの指定。初期値は
omit
- "omit" - Cookieなど認証情報を付与しない。
- "same-origin" - 同一ドメインの場合に認証情報を付与する。
- "include" - 全てのドメインで認証情報を付与する。
Cookieを付与してリクエストを送る
デフォルトではCookieは付与されないので、options.credentials
を設定して送ります。// Cookieを付与した送信 fetch('/text', { credetials : 'include' }) .then(response => response.text()) .then(text => console.log('text:', text));
リクエストヘッダーを付与する
リクエストヘッダーは、options.headers
にHeadersを付与します。// ヘッダーの付与 fetch('/text', { headers : new Headers({ 'X-MY-APP' : '12345' }) }).then(response => response.text()) .then(text => console.log('text:', text));
参考資料
さらなる詳しい情報は、以下のドキュメントをご確認ください。https://github.com/github/fetch
https://github.github.io/fetch/
Fetch 概説 - Web API インターフェイス | MDN
最後に
先月から入ったプロジェクトでfetchが使われていたので腰を据えて学んでみました。低レベルなAPIで色々とできていいですね。今後にちょっとずつ使えたらと思います。最後になりますが本ブログでは、フロントエンド・Go言語・Node.js・Python・Linux・開発関連・Swift・Java・機械学習など雑多に情報発信をしていきます。自分の第2の脳にすべく、情報をブログに貯めています。気になった方は、本ブログのRSSやTwitterをフォローして頂けると幸いです ^ ^。
最後までご覧頂きましてありがとうございました!