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

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

Promise の復習

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

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

Promie の復習

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

async/await は、 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 のコード作成のお役にたてたら幸いです。

参考

  1. async function – JavaScript | MDN
  2. Async​Function – JavaScript | MDN
  3. JavaScript の入門書
  4. async/await 入門(JavaScript)

一緒に働いてくれる仲間を募集しております!

ライトコードでは、仲間を募集しております!

当社のモットーは「好きなことを仕事にするエンジニア集団」「エンジニアによるエンジニアのための会社」。エンジニアであるあなたの「やってみたいこと」を全力で応援する会社です。

また、ライトコードは現在、急成長中!だからこそ、あなたにお任せしたいやりがいのあるお仕事は沢山あります。「コアメンバー」として活躍してくれる、あなたからのご応募をお待ちしております!

なお、ご応募の前に、「話しだけ聞いてみたい」「社内の雰囲気を知りたい」という方はこちらをご覧ください。

ライトコードでは一緒に働いていただける方を募集しております!

採用情報はこちら

関連記事