masakiのブログ Written by masaki shibayama

【非同期処理をマスター】JavaScriptのasync&awaitとは何かについて世界一わかりやすく解説【図解あり】

Programming WebApp

こんにちは。masakiです。
今回は、JavaScriptのasync&awaitについてわかりやすく解説したいと思います。

この記事の対象読者は以下のような方になります。

  • JavaScriptのasync&awaitについて詳しく知りたい方
  • 他のネット記事や教材を読んでも、イマイチしっくり来ない方
  • とにかく手っ取り早くasync&awaitを使いこなしたい方

逆に、以下のような方は想定外となります。

  • PromiseやCallbackなど、昔の非同期処理のやり方について知りたい方

今回なぜこのような記事を書こうと思ったかというと、自分自身がasync&awaitを勉強し始めた時に、

なんだこれ、マジで意味わかんない。。そもそも同期処理とか非同期処理っていう言葉の意味すらよくわからん。

となったからです。

なので、おそらく同じような悩みを抱えている方が多くいるだろうと思い、この記事を書こうと考えました。
それでは早速解説していきます。

JavaScriptのasync&awaitとは何かについて世界一わかりやすく解説

async&awaitについていきなり説明する前に、まずは同期処理と非同期処理について解説します。
ここがわからないと、おそらくasync&awaitについてもよくわからないでしょう。

同期処理と非同期処理とは

同期処理とは

同期処理とは、以下のように1つずつ前から順番に処理をしていくことです。

処理Aが終了してから処理Bに移り、処理Bが終了したら処理Cに移る、といった具合です。
これはめちゃくちゃシンプルなので、わかりやすいと思います。

普通のプログラムはこんな感じで順番に上から実行していくのですが、JavaScriptでは通信といって、バックエンドのデータをフロントエンド側で取得したりする処理が頻繁にあります。この通信には割と時間がかかるので、同期処理だけだと遅くて困ってしまうことがあるわけですね。

こちらも図にしてみると、以下のような感じです。

フロントエンドというのは、画面があったりとかユーザーが触れる側のことです。一方バックエンドというのは、データベースなどのデータを保持している部分など、ユーザーに見えない裏側といった感じです。

このフロントエンドとバックエンドでデータのやりとりをする際には、APIというものを介して通信をする必要があります。
APIとは何かについてはまた別の記事で解説しますが、ここではとりあえず、この通信の処理には時間がかかるということを抑えてもらえればと思います。

非同期処理とは

非同期処理とは、読んで字のごとく、同期処理じゃない処理のことです。
イメージとしては以下のような感じ。

上の図について解説すると、まず普通に処理Aが行われます。そして、処理Bは非同期処理です。先ほどのバックエンドとの通信のような処理だと考えてください。
先ほど述べたとおり、一般的にこのような処理には時間がかかるので、バックグラウンドで処理Bを走らせ、処理C以降については処理Bと並行して走らせるようにします。
こうすれば、処理Bが終わるのを待たずに、他の処理を走らせることができます。

このように、バックグラウンドで走らせる処理Bのような処理のことを非同期処理と言います

非同期処理の問題点

ここまでの説明を聞くと、非同期処理って便利だなーと感じると思います。
ですが、この非同期処理には問題点があります。

先ほどの図を例にしてみると、処理Bが「バックエンドからデータを取ってくる処理」、処理Dが「そのデータを使って何かしらの操作をするような処理」だった場合に、データの取得が完了する前に処理Dが実行されてしまうことになります。これではエラーになってしまいますね。

要するに、非同期処理の問題点は、いつ完了するのかが読みにくいことなわけです。

解決策はasync&await

そこで出てくるのがasync&awaitです。
まず一旦文法の話は置いておいて、async&awaitを使うと何が良いのかを説明します。

こちらも図を用意しました。
要は、async&awaitの文法を使うと、非同期処理が終わるまで待つことができるので、非同期処理が確実に完了したタイミングで処理Dを行うことができるわけです。

ここまで聞くと、以下のような疑問も湧くかと思います。

せっかく処理を裏側で走らせたのに、それを待ってしまったら意味がないんじゃないの?

この疑問に対する答えは、先ほどの図をもう一度よく見ていただくとわかると思います。
ちゃんと処理Cと非同期処理Bが並行して実行されていますよね。普通に同期処理だけだと、こんなことはできないわけです。
これが、JavaScriptを扱うにあたってasync&awaitを必ずマスターしなければならない理由です。

async&awaitの文法について

では最後に、async&awaitの文法について解説していきます。
まずは以下のような関数を例にします。


const fetchData = () => {
  console.log("処理A")
  const res = axios.get("api/users/2")  //バックエンドからデータを取得(処理B)
  console.log("処理C")
  console.log("処理D", res.data)  //取得してきたデータを使う処理
  console.log("処理E")
}

上記のfetchData()という関数は、APIを介してバックエンドからデータを取ってくるための処理です。axiosというライブラリのgetメソッドを使用しています。
上記のように書くと処理Bはバックグラウンドで実行されつつ処理C以降が走るのですが、処理Bにかかる時間が長かった場合に、処理Bが完了する前に処理Dに入ってしまうこともあるはずです。

これだと困ってしまうので、以下のように記述します。


const fetchData = async () => {
  console.log("処理A")
  const res = await axios.get("api/users/2")  //バックエンドからデータを取得(処理B)
  console.log("処理C")
  console.log("処理D", res.data)  //取得してきたデータを使う処理
  console.log("処理E")
}

使い方は簡単で、

  1. 非同期処理を含む関数にasyncをつける
  2. 処理を待ちたい非同期処理にawaitをつける

これだけです。
awaitをつけた処理は、それが終わるまで以降の処理が実行されません。
なので、async&awaitを使った上記の処理では、処理Bが完了してから処理C以降が必ず実行されます。

以上、最後まで読んでいただきありがとうございました。