JavaScript での非同期プログラミングを理解する: イベント ループの初心者ガイド
JavaScript コードの一部が順番が狂っているように見える理由を疑問に思ったことはありますか?これを理解するための鍵は、イベント ループです。
JavaScript のイベント ループは、特にさまざまな種類の非同期操作を扱う場合、理解するのが難しい場合があります。この記事では、JavaScript が 同期 と 非同期 コード、マイクロタスク と マクロタスク をどのように処理するか、そして特定のことが起こる理由を詳しく説明します。特定の順序で。
目次
-
同期コードと非同期コード
- 同期コードとは
- 非同期コードとは
- JavaScript の非同期パターン
- 同期コードと非同期コード
-
マイクロタスクとマクロタスク
- マイクロタスクとは
- マクロタスクとは
- マイクロタスク vs マクロタスク
-
イベントループ
- イベントループとは
- イベントループの仕組み
-
例
- 例 1: Promise とイベント ループを含むタイマー
- 例 2: ネストされた Promise とタイマー
- 例 3: 同期操作と非同期操作の混合
- 結論
同期コードと非同期コード
JavaScript は、同期 と 非同期 という 2 つの主な方法で操作を処理します。両者の違いを理解することは、JavaScript がタスクを処理する方法と、効率的でノンブロッキングなコードを作成する方法を理解するための鍵となります。
同期コードとは何ですか?
同期コードは JavaScript のデフォルトであり、各行が順番に次々に実行されることを意味します。例:
console.log("First"); console.log("Second");
これは出力します:
First Second
非同期コードとは何ですか?
一方、非同期コードでは、コードの残りの部分をブロックすることなく、特定のタスクをバックグラウンドで実行し、後で完了することができます。 setTimeout() や Promise などの関数は、非同期コードの例です。
setTimeout() を使用した非同期コードの簡単な例を次に示します。
console.log("First"); setTimeout(() => { console.log("Second"); }, 0); console.log("Third");
これは出力します:
First Third Second
JavaScript の非同期パターン:
JavaScript で非同期操作を処理するには、いくつかの方法があります。
- コールバック: 引数として別の関数に渡され、最初の関数がタスクを完了した後に実行される関数。
コードサンプル:
console.log("Start"); function asyncTask(callback) { setTimeout(() => { console.log("Async task completed"); callback(); }, 2000); } asyncTask(() => { console.log("Task finished"); }); console.log("End");
- Promises: Promise は、最終的に非同期関数によって返される将来の値 (またはエラー) を表します。
コードサンプル:
console.log("Start"); const asyncTask = new Promise((resolve) => { setTimeout(() => { console.log("Async task completed"); resolve(); }, 2000); }); asyncTask.then(() => { console.log("Task finished"); }); console.log("End");
- Async/Await: Async/await は Promise の上に構築された糖衣構文であり、同期的に見える非同期コードを作成できます。
コードサンプル:
console.log("Start"); async function asyncTask() { await new Promise((resolve) => { setTimeout(() => { console.log("Async task completed"); resolve(); }, 2000); }); console.log("Task finished"); } asyncTask(); console.log("End");
同期コードと非同期コード
これらの JavaScript の実行方法とそれぞれの違いをより深く理解するために、ここでは JavaScript 関数の複数の側面にわたる詳細な違いを説明します。
Aspect | Synchronous Code | Asynchronous Code |
---|---|---|
Execution Order | Executes line by line in a sequential manner | Allows tasks to run in the background while other code continues to execute |
Performance | Can lead to performance issues if long-running tasks are involved | Better performance for I/O-bound operations; prevents UI freezing in browser environments |
Code Complexity | Generally simpler and easier to read | Can be more complex, especially with nested callbacks (callback hell) |
Memory Usage | May use more memory if waiting for long operations | Generally more memory-efficient for long-running tasks |
Scalability | Less scalable for applications with many concurrent operations | More scalable, especially for applications handling multiple simultaneous operations |
This comparison highlights the key differences between synchronous and asynchronous code, helping developers choose the appropriate approach based on their specific use case and performance requirements.
Microtasks and Macrotasks
In JavaScript, microtasks and macrotasks are two types of tasks that are queued and executed in different parts of the event loop, which determines how JavaScript handles asynchronous operations.
Microtasks and macrotasks are both queued and executed in the event loop, but they have different priorities and execution contexts. Microtasks are processed continuously until the microtask queue is empty before moving on to the next task in the macrotask queue. Macrotasks, on the other hand, are executed after the microtask queue has been emptied and before the next event loop cycle starts.
What are Microtasks
Microtasks are tasks that need to be executed after the current operation completes but before the next event loop cycle starts. Microtasks get priority over macrotasks and are processed continuously until the microtask queue is empty before moving on to the next task in the macrotask queue.
Examples of microtasks:
- Promises (when using .then() or .catch() handlers)
- MutationObserver callbacks (used to observe changes to the DOM)
- Some process.nextTick() in Node.js
Code Sample
console.log("Start"); Promise.resolve().then(() => { console.log("Microtask"); }); console.log("End");
Output:
Start End Microtask
Explanation:
- The code first logs "Start", which is synchronous.
- The promise handler (Microtask) is queued as microtask.
- The "End" is logged (synchronous), then the event loop processes the microtask, logging "Microtask".
What are Macrotasks
Macrotasks are tasks that are executed after the microtask queue has been emptied and before the next event loop cycle starts. These tasks represent operations like I/O or rendering and are usually scheduled after a certain event or after a delay.
Examples of macrotasks:
- setTimeout()
- setInterval()
- setImmediate() (in Node.js)
- I/O callbacks (file reading/writing)
- UI rendering tasks (in browsers)
Code Example:
console.log("Start"); setTimeout(() => { console.log("Macrotask"); }, 0); console.log("End");
Output:
Start End Macrotask
Explanation:
- The code first logs "Start", which is synchronous.
- The setTimeout() (macrotask) is queued.
- The "End" is logged (synchronous), then the event loop processes the macrotask, logging "Macrotask".
Microtasks vs Macrotasks
Aspect | Microtasks | Macrotasks |
---|---|---|
Execution Timing | Executed immediately after the current script, before rendering | Executed in the next event loop iteration |
Queue Priority | Higher priority, processed before macrotasks | Lower priority, processed after all microtasks are complete |
Examples | Promises, queueMicrotask(), MutationObserver | setTimeout(), setInterval(), I/O operations, UI rendering |
Use Case | For tasks that need to be executed as soon as possible without yielding to the event loop | For tasks that can be deferred or don't require immediate execution |
イベントループ
イベント ループは、JavaScript がシングルスレッドであるにもかかわらず、ノンブロッキングの非同期操作を可能にする JavaScript の基本的な概念です。非同期コールバックを処理し、時間のかかる操作によって JavaScript がブロックされることなくスムーズに実行し続けることを保証します。
イベントループとは何ですか
イベント ループは、JavaScript が非同期操作を効率的に処理できるようにするメカニズムです。コール スタックとタスク キュー (またはマイクロタスク キュー) を継続的にチェックして、次にどの関数を実行する必要があるかを決定します。
イベント ループをより深く理解するには、JavaScript が内部でどのように動作するかを知ることが重要です。 JavaScript はシングルスレッド言語であり、一度に 1 つのことしか実行できないことに注意することが重要です。呼び出しスタックは 1 つだけあり、実行される関数が格納されます。これにより同期コードは簡単になりますが、サーバーからのデータの取得やタイムアウトの設定など、完了までに時間がかかるタスクでは問題が発生します。イベント ループがなければ、JavaScript はこれらのタスクを待機したままになり、他には何も起こりません。
イベントループの仕組み
1. コールスタック:
コールスタックは、現在実行されている関数が保持される場所です。 JavaScript は、コードを処理するときにコール スタックに関数を追加したり、コール スタックから関数を削除したりします。
2. 非同期タスクが開始されます。
setTimeout、fetch、Promise などの非同期タスクが発生すると、JavaScript はそのタスクをブラウザの Web API (タイマー API、ネットワーク API など) に委任し、バックグラウンドでタスクを処理します。
3. タスクがタスク キューに移動します。
非同期タスクが完了すると (タイマーが終了するか、サーバーからデータが受信されるなど)、コールバック (結果を処理する関数) がタスク キュー (Promise の場合はマイクロタスク キュー) に移動されます。 .
4. 呼び出しスタックが現在の実行を終了します。
JavaScript は同期コードの実行を継続します。コール スタックが空になると、イベント ループはタスク キュー (またはマイクロタスク キュー) から最初のタスクを取得し、実行のためにコール スタックに配置します。
5. 以下を繰り返します。
このプロセスが繰り返されます。イベント ループにより、現在の同期タスクが完了した後にすべての非同期タスクが処理されるようになります。
例
イベント ループがどのように機能するかをより明確に理解できたので、理解を確実にするためにいくつかの例を見てみましょう。
Example 1: Timer with Promises and Event Loop
function exampleOne() { console.log("Start"); setTimeout(() => { console.log("Timeout done"); }, 1000); Promise.resolve().then(() => { console.log("Resolved"); }); console.log("End"); } exampleOne();
Output:
Start End Resolved Timeout done
Explanation:
- Step 1: "Start" is printed (synchronous).
- Step 2: setTimeout schedules the "Timeout done" message after 1 second (macrotask queue).
- Step 3: A promise is resolved, and the "Resolved" message is pushed to the microtask queue.
- Step 4: "End" is printed (synchronous).
- Step 5: The call stack is now empty, so the microtask queue runs first, printing "Resolved".
- Step 6: After 1 second, the macrotask queue runs, printing "Timeout done".
Example 2: Nested Promises and Timers
function exampleTwo() { console.log("Start"); setTimeout(() => { console.log("Timer 1"); }, 0); Promise.resolve().then(() => { console.log("Promise 1 Resolved"); setTimeout(() => { console.log("Timer 2"); }, 0); return Promise.resolve().then(() => { console.log("Promise 2 Resolved"); }); }); console.log("End"); } exampleTwo();
Output:
Start End Promise 1 Resolved Promise 2 Resolved Timer 1 Timer 2
Explanation:
- Step 1: "Start" is printed (synchronous).
- Step 2: The first setTimeout schedules "Timer 1" to run (macrotask queue).
- Step 3: The promise resolves, and its callback is pushed to the microtask queue.
- Step 4: "End" is printed (synchronous).
-
Step 5: The microtask queue runs first:
- "Promise 1 Resolved" is printed.
- "Timer 2" is scheduled (macrotask queue).
- Another promise is resolved, and "Promise 2 Resolved" is printed.
-
Step 6: The macrotask queue is processed next:
- "Timer 1" is printed.
- "Timer 2" is printed last.
Example 3: Mixed Synchronous and Asynchronous Operations
function exampleThree() { console.log("Step 1: Synchronous"); setTimeout(() => { console.log("Step 2: Timeout 1"); }, 0); Promise.resolve().then(() => { console.log("Step 3: Promise 1 Resolved"); Promise.resolve().then(() => { console.log("Step 4: Promise 2 Resolved"); }); setTimeout(() => { console.log("Step 5: Timeout 2"); }, 0); }); setTimeout(() => { console.log( "Step 6: Immediate (using setTimeout with 0 delay as fallback)" ); }, 0); console.log("Step 7: Synchronous End"); } exampleThree();
Output:
Step 1: Synchronous Step 7: Synchronous End Step 3: Promise 1 Resolved Step 4: Promise 2 Resolved Step 2: Timeout 1 Step 6: Immediate (using setTimeout with 0 delay as fallback) Step 5: Timeout 2
Explanation:
- Step 1: "Step 1: Synchronous" is printed (synchronous).
- Step 2: The first setTimeout schedules "Step 2: Timeout 1" (macrotask queue).
- Step 3: A promise resolves, scheduling "Step 3: Promise 1 Resolved" (microtask queue).
- Step 4: Another synchronous log, "Step 7: Synchronous End", is printed.
-
Step 5: Microtask queue is processed:
- "Step 3: Promise 1 Resolved" is printed.
- "Step 4: Promise 2 Resolved" is printed (nested microtask).
-
Step 6: The macrotask queue is processed:
- "Step 2: Timeout 1" is printed.
- "Step 6: Immediate (using setTimeout with 0 delay as fallback)" is printed.
- "Step 5: Timeout 2" is printed last.
Conclusion
In JavaScript, mastering synchronous and asynchronous operations, as well as understanding the event loop and how it handles tasks, is crucial for writing efficient and performant applications.
- Synchronous functions run in sequence, blocking subsequent code until completion, while asynchronous functions (like setTimeout and promises) allow for non-blocking behavior, enabling efficient multitasking.
- Microtasks (such as promises) have higher priority than macrotasks (such as setTimeout), meaning that the event loop processes microtasks immediately after the current execution, before moving to the macrotask queue.
- The event loop is the core mechanism that allows JavaScript to handle asynchronous code by managing the execution order of tasks and ensuring that the call stack is clear before processing the next queue (microtask or macrotask).
The examples provided progressively illustrated the interaction between synchronous code, promises, timers, and the event loop. Understanding these concepts is key to mastering asynchronous programming in JavaScript, ensuring your code runs efficiently and avoids common pitfalls such as race conditions or unexpected execution orders.
Stay Updated and Connected
To ensure you don't miss any part of this series and to connect with me for more in-depth discussions on Software Development (Web, Server, Mobile or Scraping / Automation), push notifications, and other exciting tech topics, follow me on:
- GitHub
- X (Twitter)
Stay tuned and happy coding ???
以上がJavaScript での非同期プログラミングを理解する: イベント ループの初心者ガイドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

開発環境におけるPythonとJavaScriptの両方の選択が重要です。 1)Pythonの開発環境には、Pycharm、Jupyternotebook、Anacondaが含まれます。これらは、データサイエンスと迅速なプロトタイピングに適しています。 2)JavaScriptの開発環境には、フロントエンドおよびバックエンド開発に適したnode.js、vscode、およびwebpackが含まれます。プロジェクトのニーズに応じて適切なツールを選択すると、開発効率とプロジェクトの成功率が向上する可能性があります。
