LoginSignup
8

fetch呼び出しでasync/awaitを使わないパターン、使うパターン

Last updated at Posted at 2021-09-21

目的

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
8