Nodeのイベントループについて話しましょう
イベント ループは Node.js の基本的な部分です。メイン スレッドがブロックされないようにすることで、非同期プログラミングが可能になります。イベント ループを理解することは、効率的なアプリケーションを構築するために重要です。次の記事では、Node のイベント ループについて詳しく説明します。お役に立てれば幸いです。
あなたはしばらく Node.js を使用し、いくつかのアプリを構築し、さまざまなモジュールを試し、非同期プログラミングにも慣れてきたと思います。しかし、何かがあなたを悩ませ続けます - イベントループです。
あなたも私と同じなら、イベント ループを理解するためにドキュメントを読んだり、ビデオを見たりするのに数え切れないほどの時間を費やしてきました。しかし、経験豊富な開発者であっても、その仕組みを完全に理解するのは難しいかもしれません。そのため、Node.js イベント ループを完全に理解できるように、このビジュアル ガイドを用意しました。それでは、座ってコーヒーを飲みながら、Node.js イベント ループの世界に飛び込んでみましょう。 [関連チュートリアルの推奨事項: nodejs ビデオ チュートリアル 、プログラミング教育 ]
JavaScript での非同期プログラミング
から始めますJavaScript での非同期プログラミングのレビューが始まります。 JavaScript は Web、モバイル、デスクトップ アプリケーションで使用されますが、本質的には、JavaScript は同期、ブロッキング、シングルスレッド言語 であることを覚えておくことが重要です。短いコードスニペットを通してこの文を理解してみましょう。
// index.js function A() { console.log("A"); } function B() { console.log("B"); } A() B() // Logs A and then B
JavaScript は同期です
メッセージをコンソールに記録する 2 つの関数がある場合、コードは上から下に実行され、毎回 1 つだけ実行されます。ライン。上記のコード スニペットでは、A が B の前に記録されていることがわかります。
JavaScript がブロックしています
JavaScript は同期の性質によりブロックされています。前のプロセスにどれだけ時間がかかっても、前のプロセスが完了するまで後続のプロセスは開始されません。コード スニペットでは、関数 A が大きなコード ブロックを実行する必要がある場合、JavaScript は関数 B に分岐せずにその操作を完了する必要があります。たとえこのコードに 10 秒、あるいは 1 分かかっていたとしてもです。
お使いのブラウザでこのような状況に遭遇したことがあるかもしれません。 Web アプリケーションがブラウザーで実行され、ブラウザーに制御を返さずにコードの集中的なブロックを実行すると、ブラウザーがフリーズすることがあります。これをブロッキングと呼びます。 Web アプリケーションがプロセッサ制御をブラウザに戻すまで、ブラウザはユーザー入力の処理や他のタスクの実行を継続できなくなります。
JavaScript はシングルスレッドです
スレッドとは、JavaScript プログラムがタスクを実行するために使用できるプロセスです。各スレッドは一度に 1 つのタスクのみを実行できます。マルチスレッドをサポートし、複数のタスクを同時に実行できる他の言語とは異なり、JavaScript にはコードを実行するメインスレッドと呼ばれるスレッドが 1 つだけあります。
JavaScript の待機
ご想像のとおり、この JavaScript モデルでは、コードの実行を続行する前にデータがフェッチされるまで待たなければならないため、問題が発生します。この待機には数秒かかる場合があり、その間は他のコードを実行できません。 JavaScript が待機せずに処理を続行すると、エラーが発生します。 JavaScript で非同期動作を実装する必要があります。 Node.js にアクセスして見てみましょう。
Node.js ランタイム
Node.js ランタイムはブラウザを使わずに利用できる環境です 使用して実行しますJavaScript プログラム。コア - ノード ランタイムは、3 つの主要コンポーネントで構成されます。
- 外部依存関係 (V8、libuv、crypto など) は Node.js の必須機能です。
- C 機能は、ファイル システム アクセスやネットワークなどの機能を提供します。
- JavaScript ライブラリは、JavaScript コードを使用した C 機能の呼び出しを容易にする関数とツールを提供します。
すべての部分が重要ですが、Node.js の非同期プログラミングの主要なコンポーネントは libuv です。
Libuv
Libuv は、C 言語で書かれたクロスプラットフォームのオープンソース ライブラリです。 Node.js ランタイムにおけるその役割は、非同期操作の処理のサポートを提供することです。仕組みを見てみましょう。
Node.js ランタイムでのコードの実行
让我们来概括一下代码在 Node 运行时中的执行方式。在执行代码时,位于图片左侧的 V8 引擎负责 JavaScript 代码的执行。该引擎包含一个内存堆(Memory heap)和一个调用栈(Call stack)。
每当声明变量或函数时,都会在堆上分配内存。执行代码时,函数就会被推入调用栈中。当函数返回时,它就从调用栈中弹出了。这是对栈数据结构的简单实现,最后添加的项是第一个被移除。在图片右侧,是负责处理异步方法的 libuv。
每当我们执行异步方法时,libuv 接管任务的执行。然后使用操作系统本地异步机制运行任务。如果本地机制不可用或不足,则利用其线程池来运行任务,并确保主线程不被阻塞。
同步代码执行
首先,让我们来看一下同步代码执行。以下代码由三个控制台日志语句组成,依次记录“First”,“Second”和“Third”。我们按照运行时执行顺序来查看代码。
// index.js console.log("First"); console.log("Second"); console.log("Third");
以下是 Node 运行时执行同步代码的可视化展示。
执行的主线程始终从全局作用域开始。全局函数(如果我们可以这样称呼它)被推入堆栈中。然后,在第 1 行,我们有一个控制台日志语句。这个函数被推入堆栈中。假设这个发生在 1 毫秒时,“First” 被记录在控制台上。然后,这个函数从堆栈中弹出。
执行到第 2 行时。假设到第 2 毫秒了,log 函数再次被推入堆栈中。“Second”被记录在控制台上,并弹出该函数。
最后,执行到第 3 行了。第 3 毫秒时,log 函数被推入堆栈,“Third”将记录在控制台上,并弹出该函数。此时已经没有代码要执行,全局也被弹出。
异步代码执行
接下来,让我们看一下异步代码执行。有以下代码片段:包含三个日志语句,但这次第二个日志语句传递给了fs.readFile()
作为回调函数。
执行的主线程始终从全局作用域开始。全局函数被推入堆栈。然后执行到第 1 行,在第 1 毫秒时,“First”被记录在控制台中,并弹出该函数。然后执行移动到第 2 行,在第 2毫秒时,readFile
方法被推入堆栈。由于 readFile
是异步操作,因此它会转移(off-loaded)到 libuv。
JavaScript 从调用堆栈中弹出了 readFile
方法,因为就第 2 行的执行而言,它的工作已经完成了。在后台,libuv 开始在单独的线程上读取文件内容。在第 3 毫秒时,JavaScript 继续进行到第 5 行,将 log 函数推入堆栈,“Third”被记录到控制台中,并将该函数弹出堆栈。
大约在第 4 毫秒左右,假设文件读取任务已经完成,则相关回调函数现在会在调用栈上执行, 在回调函数内部遇到 log 函数。
log 函数推入到到调用栈,“Second”被记录到控制台并弹出 log 函数 。由于回调函数中没有更多要执行的语句,因此也被弹出 。没有更多代码可运行了 ,所以全局函数也从堆栈中删除 。
控制台输出“First”,“Third”,然后是“Second”。
Libuv 和异步操作
很明显,libuv 用于处理 Node.js 中的异步操作。对于像处理网络请求这样的异步操作,libuv 依赖于操作系统原生机制。对于没有本地 OS 支持的异步读取文件的操作,libuv 则依赖其线程池以确保主线程不被阻塞。然而,这也引发了一些问题。
- 当一个异步任务在 libuv 中完成时,什么时候 Node 会在调用栈上运行相关联的回调函数?
- Node 是否会等待调用栈为空后再运行回调函数?还是打断正常执行流来运行回调函数?
- 像
setTimeout
和setInterval
这类延迟执行回调函数的方法又是何时执行回调函数呢? - 如果
setTimeout
和readFile
这类异步任务同时完成,Node 如何决定哪个回调函数先在调用栈上运行?其中一个会有更多的优先级吗?
所有这些问题都可以通过理解 libuv 核心部分——事件循环来得到答案。
イベントループとは何ですか?
技術的に言えば、イベント ループは単なる C 言語プログラムです。しかし、Node.js では、同期コードと非同期コードの実行を調整するための設計パターンと考えることができます。
イベント ループの視覚化
イベント ループは、Node.js アプリケーションが実行されている限り実行されるループです。各ループには 6 つの異なるキューがあり、各キューには最終的にコール スタックで実行する必要がある 1 つ以上のコールバック関数が含まれています。
- まず、タイマー キュー (タイマー キュー。専門的には min-heap と呼ばれます) があり、
setTimeout## と同じ番号が保存されます # コールバック
setIntervalに関連する関数。
2 番目に、I/O キュー (I/O キュー) があります。これには、 - fs
モジュールや
httpモジュールなど、すべての非同期メソッドに関連するコールバック関数が含まれています。関連するメソッドが提供されます。
3 番目のキューは、ノード固有の関数である - setImmediate
関数に関連するコールバック関数を保持するチェック キューです。
4 番目はクローズ キュー (クローズ キュー) で、非同期タスクの終了イベントに関連付けられたコールバック関数を保存します。
- nextTick キューには、
- process.nextTick
関数に関連付けられたコールバック関数が格納されます。
Promise キューには、JavaScript のローカル - Promise
に関連付けられたコールバック関数が格納されます。
イベント ループはどのように機能しますか?
写真の矢印はヒントですが、わかりにくいかもしれません。キューの優先順位について説明します。まず知っておくべきことは、ユーザーが作成したすべての同期 JavaScript コードは非同期コードよりも優先されるということです。これは、イベント ループは呼び出しスタックが空の場合にのみ機能することを意味します。 イベント ループでは、実行順序は特定のルールに従います。習得する必要のあるルールがまだいくつかありますので、1 つずつ見てみましょう:- マイクロタスク キュー内のすべてのコールバック関数を実行します。最初に nextTick キュー内のタスク、次に Promise キュー内のタスクです。
- タイマー キュー内のすべてのコールバック関数を実行します。
- マイクロタスク キューにコールバック関数がある場合、マイクロタスク キュー内のすべてのコールバック関数
- は、各コールバック関数が タイマー キューで実行された後に実行されます。最初に nextTick キュー内のタスク、次に Promise キュー内のタスクです。 I/O キュー内のすべてのコールバック関数を実行します。
- マイクロタスク キューにコールバック関数がある場合、マイクロタスク キュー内のすべてのコールバック関数は、nextTick キュー、Promise キューの順に順番に実行されます。
- チェック キュー内のすべてのコールバック関数を実行します。
- マイクロタスク キューにコールバック関数がある場合、マイクロタスク キュー内のすべてのコールバック関数
- は、キュー内の各コールバックを チェックした後に実行されます。最初に nextTick キュー内のタスク、次に Promise キュー内のタスクです。 クローズキュー内のすべてのコールバック関数を実行します。
- 同じループの最後で、マイクロタスク キューを再度実行します。最初に nextTick キュー内のタスク、次に Promise キュー内のタスクです。
非同期タスクが libuv で完了すると、Node はいつコール スタックで関連するコールバック関数を実行しますか?
回答:コールバック関数は、コール スタックが空の場合にのみ実行されます。
ノードはコールバック関数を実行する前にコールスタックが空になるのを待ちますか?それとも通常の実行フローを中断してコールバック関数を実行しますか?
回答:コールバック関数を実行しても、通常の実行フローは中断されません。
コールバック関数の実行を遅延させる setTimeout や
setInterval などのメソッドは、いつコールバック関数を実行しますか?
回答: setTimeout
および setInterval
のすべてのコールバック関数の中で最初の優先順位が実行されます (マイクロタスク キューに関係なく)。
2 つの非同期タスク (setTimeout
と readFile
など) が同時に完了した場合、ノードはどのコールバック関数を実行するかをどのように決定しますかコールスタックの最初??一方が他方よりも優先されるでしょうか?
回答: 同時完了の場合、タイマー コールバックは I/O コールバックの前に実行されます。
これまで多くのことを学習してきましたが、下の図に示されている実行シーケンスを念頭に置いていただければ幸いです。これは、Node.js が舞台裏で何を行っているかを完全に示しているためです。非同期コードを実行する方法。
しかし、「このビジュアライゼーションを検証するコードはどこにあるの?」と疑問に思うかもしれません。イベント ループ内の各キューには実装上のニュアンスがあるため、それらについて 1 つずつ説明するほうがよいでしょう。この記事は、Node.js イベント ループに関するシリーズの最初の記事です。各キューの操作の詳細については、記事の最後にあるリンクを必ず確認してください。今は心に深い印象が残っている場合でも、特定のシナリオに到達すると、いくつかの罠に陥る可能性があります。 。
結論
このビジュアル ガイドでは、JavaScript の非同期プログラミング、Node.js ランタイム、および非同期操作の処理を担当する libuv の基本について説明します。この知識があれば、Node.js の非同期の性質を利用するコードを作成するときに役立つ強力なイベント ループ モデルを構築できます。
ノード関連の知識の詳細については、nodejs チュートリアル を参照してください。
以上がNodeのイベントループについて話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

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

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

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

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

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

ホットトピック









PHP と Vue: フロントエンド開発ツールの完璧な組み合わせ 今日のインターネットの急速な発展の時代において、フロントエンド開発はますます重要になっています。 Web サイトやアプリケーションのエクスペリエンスに対するユーザーの要求がますます高まっているため、フロントエンド開発者は、より効率的で柔軟なツールを使用して、応答性の高いインタラクティブなインターフェイスを作成する必要があります。フロントエンド開発の分野における 2 つの重要なテクノロジーである PHP と Vue.js は、組み合わせることで完璧なツールと見なされます。この記事では、PHP と Vue の組み合わせと、読者がこれら 2 つをよりよく理解し、適用できるようにするための詳細なコード例について説明します。

フロントエンド開発のインタビューでは、HTML/CSS の基本、JavaScript の基本、フレームワークとライブラリ、プロジェクトの経験、アルゴリズムとデータ構造、パフォーマンスの最適化、クロスドメイン リクエスト、フロントエンド エンジニアリング、デザインパターン、新しいテクノロジーとトレンド。面接官の質問は、候補者の技術スキル、プロジェクトの経験、業界のトレンドの理解を評価するように設計されています。したがって、候補者はこれらの分野で自分の能力と専門知識を証明するために十分な準備をしておく必要があります。

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

Django は、迅速な開発とクリーンなメソッドを重視した Python で書かれた Web アプリケーション フレームワークです。 Django は Web フレームワークですが、Django がフロントエンドなのかバックエンドなのかという質問に答えるには、フロントエンドとバックエンドの概念を深く理解する必要があります。フロントエンドはユーザーが直接対話するインターフェイスを指し、バックエンドはサーバー側プログラムを指し、HTTP プロトコルを通じてデータと対話します。フロントエンドとバックエンドが分離されている場合、フロントエンドとバックエンドのプログラムをそれぞれ独立して開発して、ビジネス ロジックとインタラクティブ効果、およびデータ交換を実装できます。

Go 言語は、高速で効率的なプログラミング言語として、バックエンド開発の分野で広く普及しています。ただし、Go 言語をフロントエンド開発と結びつける人はほとんどいません。実際、フロントエンド開発に Go 言語を使用すると、効率が向上するだけでなく、開発者に新たな視野をもたらすことができます。この記事では、フロントエンド開発に Go 言語を使用する可能性を探り、読者がこの分野をよりよく理解できるように具体的なコード例を示します。従来のフロントエンド開発では、ユーザー インターフェイスの構築に JavaScript、HTML、CSS がよく使用されます。

Golang とフロントエンド テクノロジーの組み合わせ: Golang がフロントエンド分野でどのような役割を果たしているかを調べるには、具体的なコード例が必要です。インターネットとモバイル アプリケーションの急速な発展に伴い、フロントエンド テクノロジーの重要性がますます高まっています。この分野では、強力なバックエンド プログラミング言語としての Golang も重要な役割を果たします。この記事では、Golang がどのようにフロントエンド テクノロジーと組み合わされるかを検討し、具体的なコード例を通じてフロントエンド分野での可能性を実証します。フロントエンド分野における Golang の役割は、効率的で簡潔かつ学びやすいものとしてです。

JavaScript で HTTP ステータス コードを取得する方法の紹介: フロントエンド開発では、バックエンド インターフェイスとの対話を処理する必要があることが多く、HTTP ステータス コードはその非常に重要な部分です。 HTTP ステータス コードを理解して取得すると、インターフェイスから返されたデータをより適切に処理できるようになります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法と、具体的なコード例を紹介します。 1. HTTP ステータス コードとは何ですか? HTTP ステータス コードとは、ブラウザがサーバーへのリクエストを開始したときに、サービスが

Django: フロントエンド開発とバックエンド開発の両方を処理できる魔法のフレームワークです。 Django は、効率的でスケーラブルな Web アプリケーション フレームワークです。 MVCやMTVなど複数のWeb開発モデルをサポートし、高品質なWebアプリケーションを簡単に開発できます。 Django はバックエンド開発をサポートするだけでなく、フロントエンド インターフェイスを迅速に構築し、テンプレート言語を通じて柔軟なビュー表示を実現します。 Django はフロントエンド開発とバックエンド開発をシームレスに統合するため、開発者は学習に特化する必要がありません。
