SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

基礎からはじめるReact入門

Reduxで非同期処理を行う~ES2017のasync/await構文を使って実装する方法

基礎からはじめるReact入門 第10回

async/awaitとは(2)

Promiseを同期的に記述するasync/await

 async/await構文はPromiseの仕組みを使いつつ、その見た目をガラッと変えてしまうものです。百聞は一見にしかずということで、リスト3の処理をasync/await構文で書き換えてみましょう(リスト4)。

[リスト4]async/awaitを使ったPromise処理
// async functionとして定義する
async function doFetch() { // (1)
  // /api/hogeのレスポンスが終わると代入が行われる
  const hogeResp = await fetch("/api/hoge"); // (3)
  const hogeId = translateResponse(hogeResp);

  // /api/fugaのレスポンスが終わると代入が行われる
  const fugaResp = await fetch(`/api/fuga?hogeId=${hogeId}`);
  const fugaId = translateResponse(fugaResp);
  
  // hogeIdもfugaIdも使える
  const piyoResp = await fetch(`/api/piyo?hogeId=${hogeId}&fugaId=${fugaId}`);
  const piyoId = translateResponse(piyoResp);
  
  return piyoId;
  // ここでreturnしたものがdoFetch関数が返すPromiseの結果になる
}

doFetch() // (2)
.then(piyoId => {
  // piyoIdを使った処理
})
.catch(/*エラー処理*/)

 一連の非同期処理同士で行われる結果の受け渡しが、doFetch関数の中で完結するようになり、見通しがよくなりました。(1)のように async キーワードを付けて関数を定義することで、Promiseによる非同期処理を定義できるようになります。この関数を実行すると、(2)のようにPromiseを返します。この関数をasync functionと呼びます。そして、このasync functionの中でのみ使えるのが、(3)で使われている await キーワードです。fetchの戻り値に対してthenを呼び出すのではなく、まるで同期的に処理を行うかのごとく、awaitを挟みつつ代入が行われています。

 async functionの中では通常の関数と同じように上から下へと処理が実行されますが、 await Promiseオブジェクト を評価する時点で一旦処理が止まります(図1)。この間、他所の関数では処理が続くため、画面が止まってしまうことはありません。

図1:awaitキーワードでPromiseの結果を待つ
図1:awaitキーワードでPromiseの結果を待つ

 その後、Promiseの結果が返ってきた時点(通常ならばthenが呼ばれるタイミングです)で、処理が再開されます(図2)。

図2:Promiseが完了すると処理が再開する
図2:Promiseが完了すると処理が再開する

 Promiseの結果はawaitの戻り値となり、通常の値と同じように扱われます。変数に代入できるのはそのためです。これらの仕組みによって、async/awaitはPromiseを同期処理のように扱うことができます。

async/awaitのエラー処理

 Promiseの結果がthenではなくawaitの戻り値として得られるのはわかりました。では、catchで得られるはずだったエラーオブジェクトは、どこからもらえるのでしょうか。ありがたいことに、エラーハンドリングの仕組みは誰もが知っているtry-catch構文でサポートされています。リスト1と同じ処理をasync/await構文で実現した場合、リスト5の通りの見た目になります。

[リスト5]async/awaitのエラーハンドリング
try {
  const response = await fetch("/api/hoge");
  // 通信が成功した場合の処理
} catch (error) {
  // エラーが発生した場合の処理
}

 また、async functionの中でcatchされなかったエラーは、async functionの戻り値であるPromiseオブジェクトのcatchに渡されるようになっています(リスト4の最後の行にあるcatchがそうです)。async functionの中でtry-catchによるエラー処理を行うか、async functionを呼び出した側の処理でcatchを定義するかは、開発者の好みで使い分けてください。

[コラム]async/awaitが使える環境

 async/await構文はECMAScript 2017で策定された文法です。今日では多くのブラウザに標準搭載されるようになりましたが、古いブラウザを使い続けているユーザーの手元では、そのままでは動作しません。ですが、create-react-appを使っている場合は、内部でBabel向けにasync/awaitプラグインが導入されています。JavaScriptファイルをコンパイルする際に、古いブラウザでも動く代替実装に置き換えてくれるのです。

 そのため、本記事では、async/await構文について特段の設定をせずに解説を行っています。create-react-app以外の環境でasync/await構文が使えるかどうかは、都度環境を確認しながら使用してください。

次のページ
async/await構文で掲示板アプリを作り直す

この記事は参考になりましたか?

基礎からはじめるReact入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 中川 幸哉(ナカガワ ユキヤ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/10889 2018/07/17 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー