Service Workersでプッシュ通知を受信できるようになったわけですが([1]: GCM)([2]: Web Push)、Chromeではバージョン48まではGCMで通知だけができるようになっただけで、メッセージ本体は通知を受けてからService Workerでサーバから改めて受け取るような実装をする必要があったりします。
ここで、Service Workersでは、XMLHttpRequestが使えません。その代わり、XMLHttpRequest (以下、XHR)に代わるWHATWGの仕様としてFetch APIがあり、Service WorkersではこのFetch APIを使うことになっていますので、その使い方を簡単に紹介します。
Fetch API自体は、Service Workers専用のものではなく、メインスレッドでもXHRの代わりに使うことが可能です。現時点で実装しているブラウザは、Service Workersが使えるChrome, Opera, Firefox等(Chrome, Opera等はごく一部の古いバージョンでは非対応)と、バージョン14以降のMicrosoft Edge、Safari 10.1以降となります。
なお、過去のバージョンのブラウザへの対応が必要となる場合は、Polyfillを使うと良いかもしれません。
基本的な使い方
まず、同じオリジン内のリソースをHTTP(S)のGETで単純に取得する場合は、次のようにします。
fetch('URLあるいは相対パスなど').then(...);
fetch()
の結果はPromiseで返され、resolve関数には引数としてResponse
オブジェクトが渡されます。ここで、取得した内容はBlob, ArrayBuffer, JSON, プレーンテキストのいずれかの形で受け取ることが出来ます。
fetch(url).then(function(response) {
return response.blob();
}).then(function(blob) {
// blobにBlob型で結果が渡される
...
});
fetch(url).then(function(response) {
return response.arrayBuffer();
}).then(function(arrayBuffer) {
// arrayBufferにArrayBuffer型で結果が渡される
...
});
fetch(url).then(function(response) {
return response.json();
}).then(function(json) {
// jsonにJSONオブジェクトで結果が渡される
...
});
fetch(url).then(function(response) {
return response.text();
}).then(function(text) {
// textに文字列で結果が渡される
...
});
様々なオプションを使う
fetch()
メソッドでは、JSONで様々なオプションを渡すことで、HTTPリクエストを柔軟にカスタマイズできるのが大きな特徴です。JSONで一度に指定できるのでXHRよりも扱い方が楽になっています。
fetch('URLあるいは相対パスなど', {/* JSONでオプションを指定 */}).then(...);
POSTメソッド
オプションのmethod
メンバにHTTPメソッド名を指定することが出来ます。また、メソッドが'POST'
の場合は、body
メンバにアップロードしたいデータを指定することができます。
fetch(url, {
method: 'POST',
body: new FormData(document.getElementById('<form>タグのid'))
}).then(function(response) {
return response.json();
}).then(function(json) {
...
});
fetch(url, {
method: 'POST',
body: document.getElementById('<input type="file">タグのid')).files[0]
}).then(function(response) {
return response.json();
}).then(function(json) {
...
});
クロスオリジンとクレデンシャル
CORSによるクロスオリジン接続を行いたい時は、オプションのmode
メンバに'cors'
を指定します。なお、'same-origin'
を指定すると同一オリジン以外の接続がエラーとなり、'no-cors'
を指定するとクロスオリジン接続ができない場合にエラーとならずに空のレスポンスが返されます。
fetch(url, {
mode: 'cors'
}).then(function(response) {
return response.json();
}).then(function(json) {
...
});
また、デフォルトではクッキー等のクレデンシャルをHTTPリクエストに含めないようになっています。クッキー等を付けたい場合は、次のようにします。
fetch(url, {
mode: 'cors',
credentials: 'include'
}).then(function(response) {
return response.json();
}).then(function(json) {
...
});
任意のHTTPリクエストヘッダを追加
オプションのheaders
フィールドにHeaders
オブジェクトもしくはJSONでHTTPリクエストヘッダの内容を指定することができます。
fetch('https://www.googleapis.com/userinfo/v2/me', {
headers: { 'Authorization': 'Bearer: (アクセストークン)' }
}).then(function(response) {
return response.json();
}).then(function(json) {
...
});
fetch('https://www.googleapis.com/userinfo/v2/me', {
headers: new Headers({ 'Authorization': 'Bearer: (アクセストークン)' })
}).then(function(response) {
return response.json();
}).then(function(json) {
...
});
Response
オブジェクトのその他の機能
Response
オブジェクトのheaders
プロパティにはHeaders
オブジェクトとしてHTTPレスポンスヘッダの内容が格納されます。また、status
プロパティにはHTTPレスポンスのステータスコード(200など)が格納されます。
fetch(url).then(function(response) {
console.log(response.headers.get('content-type')); // 例えば、"text/html; charset=utf-8"
console.log(response.status); // 例えば、200
});
Service Workersでfetch()
を使う場合の注意事項
プッシュ通知の受信時の処理などでfetch()
を使う場合、結果を受け取る処理のPromiseをevent.waitUntil()
メソッドに渡す必要があります。そうしなければ、fetch()
の受信処理が完了しないうちにService Workerが停止してしまいますので、ご注意下さい。
self.addEventListener('push', function(evt) {
var getEndpoint = self.registration.pushManager.getSubscription();
var confirmPush = getEndpoint.then(function(subscription) {
var form = new FormData();
form.append('endpoint', subscription.endpoint);
return fetch(pushServerUrl, {
method: 'POST',
body: form
});
});
var getPushData = confirmPush.then(function(response) {
return response.json();
});
var parseJSON = getPushData.then(function(json) {
var data = json.data;
...
});
evt.waitUntil(parseJSON);
});