恥ずかしながらFetchAPIたるものがあるのを知らなかったので、ざっくり試してみた。
Fetch API
Service Workersでも使えて、プレーンなJavaScriptのXMLHttpRequestより強力で柔軟な操作ができるそうです。
GET
fetch(api_url, {method: 'GET'}) .then((res) => { // resはResponseオブジェクト console.log( res ); // 返されたBodyをjsonにしてPromise.resolve()する return res.json(); }) .then((data) => { // api_url から返されたデータ(json) // 実際にデータを加工したり色々する console.log( data ); }) .catch((err) => { console.error( err ); });
GETメソッドの場合は第二引数のmethod: 'GET'
を省略することができます。
FetchAPIで最初で取得されるデータはResponse
オブジェクトになっており、res.json()
を実行することで返されたデータのBodyをJSON形式にしてPromise.resolve()
に渡すようになっています。
JSON以外にも次のようにArrayBuffer
, Blob
, FormData
, String
にすることもできます。
- ArrayBuffer:
res.arrayBuffer()
- Blob:
res.blob()
- FromData:
res.formData()
- String:
res.text()
詳しくはドキュメント: Response - Web API | MDNを参照
POST
fetch(api_url, { method: 'POST', // 送信するデータ body: post_data }) .then((res) => res.json) .then((data) => console.log( data )) .catch((err) => console.error( err ));
POSTで送信するデータはbody
オプションに指定します。
method
をPUT
, DELETE
にすればPUT, DELETEのリクエストも送ることが出来ます。
PUT
fetch(api_url, { method: 'PUT', body: post_data }) .then((res) => ...)
DELETE
fetch(api_url, { method: 'DELETE', }) .then((res) => ...)
クロスオリジン (クロスドメイン)の送信
クロスオリジンで通信を行いたい時はmode
オプションにcors
を指定します。
fetch(api_url, { mode: 'cros' }).then((res)...)
mode オプション
same-origin
: *default 同じドメイン(same origin)のみ許可。クロスオリジンは接続エラーcors
: クロスオリジンを許可。レスポンスは表示できるヘッダがCache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
に限定されるcors
andbasic
responses are almost identical except that a cors response restricts the headers you can view toCache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
, andPragma
.no-cors
: CORSヘッダーを持たないopaque
レスポンスを返すオリジン用。接続ができない場合にエラーとならずに空のレスポンスが返される。no-cors
is intended to make requests to other origins that do not have CORS headers and result in anopaque
response, but as stated, this isn't possible in the window global scope at the moment.
no-cors
についてはイマイチ理解が出来ていないのですが、クロスオリジンにリクエストを送る際はmode: 'cors'
としておけば良さそうです。
詳しくは Request.mode - Web API | MDN・Response Types Introduction to fetch() | web | Google Developersを参照
クレデンシャル (認証情報: credentials)
クッキーなどのクレデンシャルを送る場合はcredentials
オプションをinclude
にする
fetch(api_url, { credentials: 'include' }).then((res) => ... )
credentials オプション
omit
: *default リクエストにクレデンシャル(認証情報)を含まないsame-origin
: 同一オリジンの場合だけクレデンシャル(認証情報)を送るinclude
: クレデンシャル(認証情報)の入ったリクエストを送る
cf. Sending_a_request_with_credentials_included | Fetch 概説 | MDN
カスタムヘッダー
クロスオリジン・クレデンシャル以外にもcache
, header
, redirect
, referrer
リクエストのヘッダーのオプションが用意されています。
e.g. JSONで指定したヘッダー情報を追加
fetch(api_url, { header: { 'Content-Type': 'application/json' } }).then((res) => ... )
Header情報はHeaderインターフェースで色々と独自な設定が可能なようです。
cf. Headers | FetchAPI 概説 | MDN
対応ブラウザとPolyfill
Can I use... Support tables for HTML5, CSS3, etc
この記事を書いた2019年1月時点では、IE11を含めたIEと、IE Mobile, Blackberry といった幾つかのモバイルブラウザで未対応をなっているようです。
Polyfillが用意されているのでこれらの非対応サポートブラウザで使用するにはこちらを利用するのが良さそうです。
Browser Support
babelしてみた
babel7で自動的にPolyfillがロードされる設定でFetchAPIが非対応ブラウザーようにバベれるか一応試してみました。
babel.config.js
const presets = [ ["@babel/preset-env", { "modules": false, "targets": ["ie > 10"], "useBuiltIns": "usage", }] ]; module.exports = { presets }
index.js
fetch('http://localhost:3000', { method: 'GET' }) .then((res) => res.json()) .then((data) => console.log(data)) .catch((err) => console.error(err));
👇$ yarn babel
バベる
bandle.js
// 略 fetch('http://localhost:3000', { method: 'GET' }).then(function (res) { return res.json(); }).then(function (data) { return console.log(data); }).catch(function (err) { return console.error(err); });
Promise
のPolyfillもロードされませんでした。
babel7デフォルトの@babel/preset-env
ではFetchAPIはPolyfillされないようです。
FetchAPIを使っているプロジェクトで非サポートブラウザ対応をする場合は配布されているPolyfillを使用するのが良さそうです。(babelで読み込ませられるのかな?)
感想
then
を二重にしないといけないのが最初ちょっとキモかったですがjQueryを使わない場合は、生JSのXMLHttpRequestで書くよりタイプ数も少なくて済むし見通しもよいので良さそうだと思いました。(生JS...
[参考]