1. HOME
  2. ブログ
  3. IT技術
  4. 【JavaScript】 async/await で非同期処理をわかりやすく記述する

【JavaScript】 async/await で非同期処理をわかりやすく記述する

async/await という仕組み

本記事では、 JavaScript の非同期処理を扱うための async/await という仕組みについて取り上げます。

async/await は、 Promise を利用した非同期処理をよりわかりやすく記述できます。

本題へ進む前に Promie の復習をしておきましょう!

Promise の復習

async/await は、 Promise の仕組みを利用しているため、Promise への理解が大切だからです。

非同期関数を作成するときに Promise が利用できます。

Promiseの状態

Promise には、以下の状態があります。

apending: 初期状態、実行中。成功も失敗もしていない
fulfilled: 処理が完了した状態。then メソッドを呼び出す
rejected: 処理が失敗した状態。then メソッドと catch メソッドを呼び出す。

  1. resolve() が呼ばれると、fulfilled の状態になります。
  2. rejected() が呼ばれると、rejected の状態になります。

Promise の then

then()  は、 Promise のインスタンスの状態が fulfilled となったときに実行する関数を登録できるインスタンスメソッドです。

then() は、以下のように定義されています。

  1. onFulfilled : fulfilled の状態のとき(resolve が呼ばれたとき)に実行される関数
  2. onRejected : rejected の状態のとき(reject が呼ばれたとき)に実行される関数

Promise の catch

reject()  とは、 Promise のインスタンスの状態が rejected となったときに実行する関数を登録するインスタンスメソッドです。

  1. onRejected : rejected の状態のとき(reject が呼ばれたとき)に実行される関数

Promise の関連記事

async とは

非同期関数を定義する関数定義です。

async function で非同期関数を定義できます。

async function は Promise インスタンスを返却します。

上記の例で定義した asyncFunc は、以下の関数と同義です。

async function は、以下のことを行います

  1. async function 中でreturn されたとき、戻り値で Promise.resolve します
  2. async function 中でPromisereturn されたときは、その返り値のPromiseをそのまま返します。
  3. async function 中で例外や値を throw したときは、その値で Promise.reject をします。

async function を実際に使ってみる

async function を実際に書いてみて、どのように動作するか確認していきましょう。

async function の中で return

async function で定義された関数内でreturnされると、その return の返り値で Promise.resolve が実行されます。

つまり、 async function で定義された関数は then() でつなげることができます。

async function の中で Promise を return

async function で定義された関数内で Promisereturn すると、そのPromise がそのまま返却されます。

ですので、 then()  や catch()  で処理を受けることができます。

aysnc function の中で throw

async function で定義された関数内で throw された場合、その throw の値でPromise.reject が実行されます。

ですので、 catch() でエラー処理を行えます。

上記の例で見てもらったらわかるのですが、結局 async functionPromise を返すだけの関数です。

外部の関数からaync function を呼び出すときは、Promise を返却する非同期関数であると認識していればいいです。

await 式

await 式の使いかた

async function では、awaitを利用できます。

await 式を利用すると、指定した Promise の結果が返されるまで処理を待機します。

Promise の状態が、 fulfilled または rejected になると、処理を続行します。

wait()  関数は、 setTimeout()  を Promise でラップした非同期関数です。

そのため、普通は wait()  関数で処理が止まることはありません。

await式を利用しなければ、ターミナルにはすぐに「1 2」と表示されます。

ですが、await 式を利用しているため、上記のコードでは wait() 関数が処理を終了するまで、次の処理 ( console.log(2) ) が評価されません。

ですので、上記のコードを実行してみると、コンソールに 1 が表示されてから、約 3 秒経過した後、2 が表示されます。

await 式の嬉しいところ

await 式を利用することで、非同期処理でありながら、同期処理のように上から順番に処理するように記述できます。

非同期関数でありながら、見通しのよいコードが記述可能となります。

サンプルコード中の関数 promiseFunc()  は、処理に約1秒かかります。

asyncFunc()  では await 式で処理が終了するのを待機して、各変数に格納しています。

await 式の利用によって同期処理のような記述になっています。

※ 1つずつ関数の終了を待っているため、このコードは実行に約3秒以上かかります。このままでは問題なので、次の章で効率的に処理できるよう改善します。

async の中で Promise.all()

await を使うと、非同期処理を同期処理のように記述できわかりやすいです。

ですが、連続で記述された非同期処理を1つずつ待ってしまってはムダな待ち時間が発生します。

その問題を解決するには、 Promise.all()  というメソッドを利用します。

Promise.all()

Promise.all()  は、引数に非同期関数の配列を受け取り、Promise インスタンスを返すメソッドです。

非同期処理の結果は、配列として戻ってきます。

Promise.all() に引数として与えられた非同期関数の配列は、並行して実行されます。

そのため、非同期処理を効率的に処理できます。

すべての非同期関数の処理が終わるとPromise.all() で返ってくる Promise インスタンスの状態は fulfilled になります。

await 式は返された Promise インスタンスが fulfilled になるまで待機します。

つまり await 式は、Promise インスタンスを返却する処理と組み合わせることができます。

よって await 式は、 Promise.all() メソッドとも組み合わせることができます。

サンプルコード

[結果]
[ 2, 4, 6 ]

サンプルコード中の関数 promiseFunc()  は処理に約1秒かかり、他の変数やデータベースに影響を与えない独立した関数です。

並行して処理を行っても問題がないので、 Promise.all()  で実行しています。

そして、実行結果を await 式で受け取って、 console.log  でターミナルに表示しています。

実行してみると、約1秒で処理が終了します。

前の章では同じような処理に3秒かかっていたので、改善できています。

このように、互いに影響を及ぼさない非同期処理は、 Promise.all()  を利用することで効率的に処理できます。

await 式の中で例外

await 式の中で、 Promiserejected になった場合、その場でエラーを throw します

async function 内で発生した例外は自動的にキャッチされます。

何も処理しなければ、async functionrejectedPromise を返します。

サンプルコード

以下サンプルコードです。

エラーが throw されるので try...catch でエラーをキャッチすることもできます。

async function 内ではエラーを throw していないので、fulfilledPromise が返されることになり、asyncFaile().then は呼ばれますが、asyncFaile().catch は呼ばれません。

もし、上位の関数でエラー処理したい場合はcatchしたのち、再び throw してください。

async/await の対応状況

Chrome、Firefox、Edge、Safari といった最新ブラウザは対応済みです。

IE11 は未対応です。

ECMAScript 2016+ compatibility table

もし、IE もサポートに含めるのなら、Babel でトランスパイルする必要があります。

さいごに

以上、async/await についてでした。

それでは、最後に、今回の内容をまとめてみます!

  1. async/await 式で非同期処理を扱える
  2. async function で定義された関数は、Promise インスタンスを返す
  3. await 式は、Promise インスタンスが fulfilled の状態になるまで、次の処理を評価しない
  4. await 式は、Promise.all のような Promise インスタンスを返す処理と組み合わせることができる

非同期処理の async/await についてでした。

本記事が JavaScript のコード作成のお役にたてたら幸いです。

こちらの記事もオススメ!

書いた人はこんな人

広告メディア事業部
広告メディア事業部
「好きを仕事にするエンジニア集団」の(株)ライトコードです!

ライトコードは、福岡、東京、大阪の3拠点で事業展開するIT企業です。
現在は、国内を代表する大手IT企業を取引先にもち、ITシステムの受託事業が中心。
いずれも直取引で、月間PV数1億を超えるWebサービスのシステム開発・運営、インフラの構築・運用に携わっています。

システム開発依頼・お見積もり大歓迎!

また、現在「WEBエンジニア」「モバイルエンジニア」「営業」「WEBデザイナー」「WEBディレクター」を積極採用中です!
インターンや新卒採用も行っております。

以下よりご応募をお待ちしております!
https://rightcode.co.jp/recruit

関連記事

採用情報

\ あの有名サービスに参画!? /

バックエンドエンジニア

\ クリエイティブの最前線 /

フロントエンドエンジニア

\ 世界を変える…! /

Androidエンジニア

\ みんなが使うアプリを創る /

iOSエンジニア