目的
fetchを呼び出す際にasync/awaitを使うパターンと使わないパターンをまとめます。
もっとこう書くとスマートだとか、この処理忘れてるとかあったらコメントでご指摘ください。
Promiseのまま扱うパターン
エラー処理を考えないシンプルなパターン
// Promiseのまま扱う際のfetchの使い方
function fetchNormal(){
// 気象庁の今日の東京の天気API(JSON)
const url = 'https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json';
const promise = fetch(url);
promise
.then(response => response.json())
.then(jsondata => {
showResult("result: " + JSON.stringify(jsondata));
});
}
ポイント
- fetchの戻り値はPromiseです。
- Promiseは、fetch呼び出しの直後に(urlへの非同期通信が完了する前に)戻されます。
- その戻り値のPromiseに対して.then(response => response.json())を呼び出します。
- 最初のPromiseはまだ完了していませんので、これは「fetchが終わったらresponse=>response.json()を実行してね」という意味になります。
- そしてそのthen()の戻り値もまたPromiseです。このPromiseもまだ終わっていません。
- response.json()のPromiseが完了したら、jsondata => {...}が実行されます。
- 大事なことは、fetchNormal()の呼び出し自体は一瞬で完了するという点です。
エラー処理を含むパターン
// 通常のfetchの使い方
function fetchNormal(){
// 気象庁の今日の東京の天気API(JSON)
const url = 'https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json';
//const url = 'http://abc'; // TypeError: Failed to fetch
//const url = 'abc'; // status=404
//const url = ''; // status=200 & undefined json.
const promise = fetch(url);
promise
.then(response => {
// レスポンスステータスのチェック。200以外でもresponseが返ればここへ来る。ネットワークエラー等の場合、then()にはこないでcatch()へ行く。
if (!response.ok) {
// 200以外ならばエラーメッセージを投げる
throw new Error(`response.status = ${response.status}, response.statusText = ${response.statusText}`);
}
return response.json(); // jsonデータの取得結果をPromiseで返す。
})
.then(jsondata => {
showResult("result: " + JSON.stringify(jsondata));
}).catch(err => {
showResult("err: " + err);
});
}
ポイント
- thenの呼び出しをチェーンできます。
- 例外はcatchメソッドで受けます。
async/awaitを使うパターン
エラー処理を考えないシンプルなパターン
// async/awaitを使ったfetchの使い方
async function fetchAsync(){
// 気象庁の今日の福井の天気API(JSON)
const url = '';//'https://www.jma.go.jp/bosai/forecast/data/overview_forecast/180000.json';
const response = await fetch(url);
const jsondata = await response.json();
showResult("result : " + JSON.stringify(jsondata));
}
ポイント
- fetch(url)の結果(Promise)をawaitしているので、実際にレスポンスが返るまでこれ以降の処理は保留されます。
- しかし、実際にはfetchAsync()の呼び出しはここで一旦終了し、未完了のPromiseが返されています。
- fetch(url)の結果のレスポンスが返るとresponseにレスポンスオブジェクトが格納されます。
- 次にresponse.json()を実行します。この結果もPromiseであり、awaitしているので、jsonデータを生成するまでこれ以降の処理は保留されます。
- 何度も言いますが、とっくにfetchAsync()自体の呼び出しは終了しており、呼び出し元の後続の処理が実行されています。ここで処理が保留されているのはJavascriptエンジンの魔法であり、ここで処理がブロックされているわけではありません。詳しくはこの記事をどうぞ。
- respon.json()の処理が完了し、結果がjsondataに格納されます。
- jsondataを表示します。
- then()の連結よりも、順番に処理が実行されることが明確に分かりやすくなっています。
エラー処理を含むパターン
// async/awaitを使ったfetchの使い方
async function fetchAsync(){
// 気象庁の今日の福井の天気API(JSON)
const url = '';//'https://www.jma.go.jp/bosai/forecast/data/overview_forecast/180000.json';
//const url = 'abc'; // status=404 Not Found
//const url = ''; // status=200 & undefined json.
//const url = 'http://google.com'; // TypeError: Failed to fetch (CORS制約)
try {
const response = await fetch(url);
if (!response.ok) {
// OK以外ならばエラーメッセージを投げる
throw new Error(`response.status = ${response.status}, response.statusText = ${response.statusText}`);
}
const jsondata = await response.json();
showResult("result : " + JSON.stringify(jsondata));
}
catch (err) {
showResult("err: " + err);
}
}
ポイント
- 発生した例外は通常のtry-carch構文でキャッチできます。
#サンプルソース
https://codepen.io/jun1sfukui/pen/jOwaoGq?editors=0011