[フロントエンド] 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をフォローして頂けると幸いです ^ ^。
最後までご覧頂きましてありがとうございました!






