🐵

JavaScript 同期処理・非同期処理について

2024/02/25に公開

はじめに

スレッド・メインスレッドについて

スレッドとは、プログラムの開始から終了までの一連の流れのこと。
ブラウザ上で、JavaScriptのコードが実行されるスレッドは、メインスレッド。
メインスレッドは、1つのスレッド。並列したコードは実行できない。

同期処理と非同期処理の基本的な違いについて

  • 実行順序
    同期処理では処理が順番に行われ、非同期処理では複数の処理が並列に行われる。
  • ブロッキングの有無
    同期処理は処理中のタスクが終わるまで次のタスクに移れない(ブロッキング)、非同期処理はタスクの完了を待たずに次のタスクに移る(ノンブロッキング)。
  • 処理の効率
    同期処理はシンプルで理解しやすいが、タスクの処理時間が全体の処理時間に直接影響する。非同期処理は複雑さが増すが、効率的にタスクを管理できる。

同期処理とは

メインスレッド上で、1行ずつ順番に実行される処理。
1つのスレッドで、前の処理の完了を待ってから次の処理を実行する。
この方式では、あるタスクの処理がブロック(停止)すると、全体の処理がそのタスクが完了するまで待つ必要がある。

非同期処理とは

非同期処理は、メインスレッドで実行される処理から一時的に「切り離された」タスクを指す。
非同期処理の特徴は、

  • 処理が完了するのを待たずに、次の処理が実行される
    これにより長時間実行される処理や外部リソースへのアクセスが他の処理の実行をブロックしないようにする。

例え

A→B→Cの処理があります。
Bが非同期処理の場合

  1. Aの実行: メインスレッドでAの処理が実行されます。
  2. Bの非同期実行: Bの処理が開始されますが、これはメインスレッドから「切り離され」、非同期で実行されます。具体的には、Bの処理はメインスレッドの実行フローとは独立してバックグラウンドで処理され、Bの完了をメインスレッドが待つことはありません。
  3. Cの実行: Bの処理が完了するのを待たずに、メインスレッドはCの処理に進みます。
  4. Bの完了: Bの非同期処理がいずれ完了すると、その結果はメインスレッドで処理されるか、コールバック関数、Promiseの解決、async/awaitなどを通じて取り扱われます。
console.log('Aの処理を開始します。');

// Bの処理(非同期処理)
setTimeout(() => {
  console.log('Bの処理(非同期処理)が完了しました。');
}, 2000); // 2000ミリ秒(2秒)後に実行

console.log('Cの処理を開始します。');

実行結果

Aの処理を開始します。
Cの処理を開始します。
Bの処理(非同期処理)が完了しました。

同期・非同期処理の実世界の例

  • 「レストランでの注文」の例え話を使って同期処理
    あなたがレストランに行って、注文します。
    あなたが、店員さんにコーヒーを頼みました。
    店員さんは、コーヒーを用意してから次のお客さんの注文を取りに行くという方法で
    働いています。
    この場合、店員さんはあなたのコーヒーが用意できるまで、他の仕事は一切できません。
    このプロセスが同期処理に似ています。
    一つのタスクが完了するまで次のタスクには移れず、処理がブロックされます。

  • 「レストランでの注文」の例え話を使って非同期処理
    今度は、あなたがコーヒーを注文した後、店員さんはキッチンにその注文を伝え、
    コーヒーが用意されるのを待つ間に他のテーブルの注文を取りに行ったり、
    別のお客さんに食事を運んだりします。
    コーヒーが用意できたら、店員さんはあなたのテーブルにそれを届けます。
    このプロセスが非同期処理に似ています。
    店員さん(メインスレッド)は、コーヒーが用意される(時間のかかるタスクが完了する)のを待つ間に、他のタスクを続けることができます。
    コーヒーが用意できたら(非同期タスクが完了したら)、それに応じた処理(コールバック)が行われます。

まとめ

今回は、JavaScriptの同期・非同期処理にまとめていきました。
私自身、普段からasyncawaitなど非同期処理を使用していますが、
メインスレッドなどのことなどは意識していませんでした。
実例を交えることによって、少しずつ理解できました。
次は、Promiseasyncawaitの違いについて調べたいです。

Discussion