35
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

35
17
0

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
  3. You can use dark theme
What you can do with signing up
35
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?