UPDATE:2021.12.3
- CATEGORY
JavaScriptの同期処理と非同期処理をやさしく解説します。
アプリコットデザインに勤める以前はプログラマーとシステムエンジニアの職に就いていたコーダーのさやさんです。
実はWEB制作にもプログラムの知識が不可欠です。
今回はWEB制作に欠かせないプログラミング言語「JavaScript」の基本の一つ「同期処理と非同期処理」を、クイズを例に説明していきます◎
今回の記事は…
目次
はじめに
まずはこちら(アイキャッチ)のクイズです。【問題】
「美味しくてはやいと噂のお店「JavaScript」で
食事、飲み物、デザートの順番に食事を注文しました。
しかしお店の店員は非同期処理でした。
この場合、食事はどのように運ばれてくるでしょう?」
これは一体どういう意味でしょう?
ちょっとまだよくわからないと思います。
次にこちらのサイトのローディングアニメーションをご覧ください。
アプリコットデザインで制作させていただきました「柴犬ラク」君のサイトです。
https://shibainuraku.com/
ローディング時、まずは音符がポップして楽しい雰囲気ですね!
その後でカーテンが開き、そしてラク君たち楽団がたのしく演奏しながら登場しています。
ローディングの最初からラク君たちの音楽が聞こえてくる感じでワクワクしますね!
さて、このローディングの一連の流れ「音符」→「カーテンが開く」→「楽団が登場」はどのように作られているのでしょうか?
一連の流れを形作っているのは「JavaScript」です。
ところで「JavaScript」を扱ったことがある方なら、
「音符」→「カーテンが開く」→「楽団が登場」の流れを表現するのが実は簡単ではないと気付くのではないでしょうか?
実はJavaScripは「順番通りに処理する」ということが少し難しいのです。
その理由を以下より詳しく説明していきますね。
同期処理と非同期処理について
同期処理とは(先の処理が終わるまで次の処理は実行されない)
処理①
↓
処理②
↓
処理③
とてもわかりやすいですね!
非同期処理とは
(先の処理が終わらなくとも、次の処理が実行される)
処理①
処理②(実行に5秒かかる処理)
処理③
この場合、上記が同期処理であった場合は「処理②」の処理が終わるまで③は実行されません。
しかし非同期処理であった場合、処理②が実行されたと同時に終わりと待たずに③は実行されます。
もう少し具体的な例を記載します。
上記はコンソールログに文字を出力する処理です。
console.log(処理①);
setTimeout(function(){console.log("処理②")},5000);
console.log(処理③);
処理自体は上から順番に実行されますが、処理②は意図的に処理の終了に5秒の時間がかかるようにしています。
なのでコンソールに出力される文字の順番は以下のようになります。
処理①
処理③
処理②
処理②の終了(5秒)を待たずに処理③の出力が実行されました。
これが非同期処理です。
JavaScriptは同期処理であり、非同期処理である
JavaScriptは同期処理であり、非同期処理でもあります。JavaScriptは記述した順番通りに処理を実行します。つまりそれは同期処理です。
以下の例でも処理①を実行(=出力)、処理②を実行(=タイマーに登録)、処理③を実行(=出力)するので同期処理となります。
しかし実行結果については処理②の出力を待たずに処理③を出力するので非同期処理となります。
console.log(処理①);
setTimeout(function(){console.log("処理②")},5000);
console.log(処理③);
(例の他にも様々な場面で非同期処理となります)
このようにJavaScriptは同期処理であり非同期処理でもあるので、順番通りに実行させるのが実は難しいのです。
クイズの答え
JavaScriptが基本的に記述通りの順番で処理してくれることは前述のとおりです。しかし処理の記述が「5秒後に次のアニメーションを実行してほしいな」という場合、
JavaScriptは処理自体は記述した順番通りに処理してくれますが、実行結果に関しては順番通りになるとは限らない…ということがおわかり頂けたと思います。
ここで冒頭のアイキャッチの問題の答えです。
JavaScriptの処理の多くは非同期処理で実行されます。 それは「順番通りに処理してほしい」という状況の場合、処理によって終了する時間がまちまちになるケースが多いからです。
(ゆっくりとしたフェードを表現したい場合など、意図的に一つの処理の完了時間を遅らせることもあります)
食事が出てきた時、直ぐに食べ終えることは出来ませんよね?
現実では店員さんは一つの食事を食べ終えた段階で次の食事を提供しますが、
JavaScriptの場合は食事中であっても容赦なく次の食事をテーブルに持ってきます。
(一見やや迷惑ですが、JavaScriptの店員さんは仕事を早く終わらすことが重要なのでこうなるのです)
プログラムも大体一つの処理完了までに多少の時間がかかり、その間に次の処理を実行するので実行結果は非同期処理となるわけです。
でも食事しているのに次の食事を持ってこられても困るという場合、多いですよね。
JavaScriptの店員さんも融通がきかないわけではないので、
処理の完了を待ってから次の処理をする(同期処理にする)という命令もちゃんとあります。
JavaScriptで順番通りに処理する方法
基本的に非同期処理となるJavaScriptは、以下の記述を行うことで同期処理が可能です。・Promise
・async/await
(メンテナンスに影響しますね)
Promiseは処理が複雑になる場合に可読性が保たれるのでおすすめの記述方法です。
async/awaitはPromiseよりもさらにコードが簡潔になる記述です。
最後に
JavaScriptは意識してコードを書かないと非同期処理となってしまうことがおわかり頂けたでしょうか。そして非同期処理になると「順番通りに処理する」ということが難しくなってしまいます。
逆に非同期と同期を理解するとJavaScriptで表現できる幅が広がります◎