HTML/CSS
アイキャッチ 猫

JavaScriptは同期的でシングルスレッドの処理で実行されていますが、非同期処理が可能な言語です。
ここでは、非同期処理と同期処理・スレッドについてまず説明し、その後処理の順番について説明していきます。

同期処理と非同期処理

同期処理

同期処理はプログラムの記述順に1つずつ実行されます。
そのため、次の処理は前の処理が終わらないと実行することができません。

非同期処理

非同期処理は同期処理と異なり処理が実行する準備をしている空き時間の間に、別の処理を実行することができます。

この説明だけだと、非同期処理は並列で色んな処理ができるってこと?と思うかもしれません。

答えは 「No」 です。

あくまで、準備している空き時間を活用しているだけなので、並列で複数の処理ができるわけではありません。
並列処理を行うためにはマルチスレッドで処理を実行する必要がありますが、JavaScriptはシングルスレッドで動きますので、並列処理ではなく、並行処理と言えます。

並列処理と並行処理の違いはこちらです。

  • 並列処理
    物理的に複数の処理を同時に実行することができる
  • 並行処理
    常に1つの処理のみ実行しているが、タイミングを見計らって処理を切り替えて処理を効率よく実行する
    同時に実行しているように見せかけている

スレッドについて

先ほどシングルスレッドマルチスレッドについて話が出てきましたが、スレッドとは何でしょうか。

スレッドとは、1つ1つ実行する処理を表します。

シングルスレッドはその名の通り1つの処理を実行することができます。

対し、マルチスレッドは複数の処理を実行することができます。

これを先ほどの並列処理と並行処理に当てはめると、このようになります。

  • 並列処理・・・マルチスレッドで実行
  • 並行処理・・・シングルスレッドで実行

JavaScriptはシングルスレッドのため、並行処理をしていることになりますね。

処理の順番

さて先述のようにJavaScriptはシングルスレッドであることが理解できましたが、並行処理をしているということは、処理の順番が入れ替わってしまうことがあります。

JavaScriptは上から順番でキューに関数を登録し、処理しています。
しかし、処理が同期的なものと非同期的なものによって、順番が入れ替わることがあります。

<上から順番に処理する>

console.log("one");
console.log("two");
console.log("three");
one
two
three

<順番が入れ替わっている>

console.log("one");
setTimeout(function(){console.log("two")}, 0);
console.log("three");
one
three
two

順番が入れ替わっているパターンでは「setTimeout」関数のタイマーを0ミリ秒で設定しています。
ここで不思議なのは、タイマーは0ミリ秒…つまり待ち時間なしで実行するように記述されていますが、実際の実行結果はone→three→two2行目と3行目の順番が入れ替わっています。

キューに登録されているのは、
 1. ログ表示 ”one”
 2. タイマー登録 0ミリ秒
 3. ログ表示 ”three”
この3つの処理になります。
つまり、この時点では、「ログ表示 ”two”」はキューにまだ登録されていないのです。

では、いつ「ログ表示 ”two”」はキューに登録されるのか?

それは、同期処理が全て終わってからです。

なので、キューの登録の順番は、
同期処理
 1. ログ表示 ”one”
 2. タイマー登録 0ミリ秒
 3. ログ表示 ”three”
同期処理の登録完了後、非同期処理
 4.ログ表示 ”two”
となります。

だから先ほどの実行結果のように、順番が入れ替わります。

まとめ

今回はJavaScriptの非同期処理と同期処理、処理の順番について、説明していきました。
JavaScriptで開発するためには、このあたりをまず始めに理解しておきたいところですね!

本記事の作成にあたり、こちらのサイトを参考にさせていただきました。
ありがとうございます。

・JavaScriptの実行キューの感覚を掴む
・JavaScriptの同期、非同期、コールバック、プロミス辺りを整理してみる

非同期処理を同期的に処理する方法については、別の記事にしたいと思います。
ご覧いただき、ありがとうございました。