Node.jsのイベントループ(Event Loop)とスレッドpool_node.jsの詳細説明
ノードの「イベント ループ」は、大規模な同時実行と高スループットを処理する機能の中核です。これは最も魔法の部分であり、これによれば、Node.js は基本的に「シングルスレッド」として理解され、同時にバックグラウンドでの任意の操作の処理も可能になります。この記事では、イベント ループがどのように機能するかを説明し、その魅力を感じていただけるようにします。
イベント駆動型プログラミング
イベント ループを理解するには、まずイベント駆動型プログラミングを理解する必要があります。 1960年に登場しました。現在、UI プログラミングではイベント駆動型プログラミングが頻繁に使用されています。 JavaScript の主な用途の 1 つは DOM と対話することなので、イベントベースの API を使用するのは自然なことです。
簡単に定義すると、イベント駆動型プログラミングは、イベントまたは状態の変化を通じてアプリケーションのフローを制御します。一般にイベント監視を通じて実装され、イベントが検出されると (つまり、状態が変化すると)、対応するコールバック関数が呼び出されます。おなじみですね?実際、これは Node.js イベント ループの基本的な動作原理です。
クライアント側の JavaScript 開発に精通している場合は、DOM 要素と組み合わせてユーザー インタラクションを提供するために使用される、element.onclick() などの .on*() メソッドについて考えてみましょう。この動作モードでは、単一のインスタンスで複数のイベントをトリガーできます。 Node.js は、サーバー側のソケットや「http」モジュールなどの EventEmitters (イベント ジェネレーター) を通じてこのパターンをトリガーします。 1 つ以上の状態変更を単一のインスタンスからトリガーできます。
もう 1 つの一般的なパターンは、成功と失敗を表現することです。一般に、2 つの一般的な実装方法があります。 1 つ目は、「エラー例外」を通常はコールバック関数の最初のパラメータとしてコールバックに渡すことです。 2 つ目は Promises デザイン パターンを使用し、ES6 を追加しています。注* Promise モードは、次のようなコールバック関数の深いネストを避けるために、jQuery と同様の関数チェーン記述方法を使用します。
よくある誤解は、イベント エミッターもイベントの起動時に本質的に非同期であるということですが、これは正しくありません。以下は、これを示す簡単なコード スニペットです。
EventEmitter.call(this);
}
util.inherits(MyEmitter, EventEmitter);
MyEmitter.prototype.doStuff = function doStuff() {
console.log('before')
エミッター.emit('火')
console.log('after')}
};
me.on('火', function() {
console.log('emit fired');
});
// 出力:
// 前
// 発砲される
// 後
である必要があります
// 前
// 後
// 発砲される
EventEmitter は、非同期で完了する必要がある操作を通知するために使用されることが多いため、非同期的に動作することがよくありますが、EventEmitter API 自体は完全に同期しています。リスニング関数は内部的に非同期で実行できますが、すべてのリスニング関数は追加された順序で同期的に実行されることに注意してください。
メカニズムの概要とスレッドプール
ノード自体は複数のライブラリに依存しています。その 1 つは、非同期イベント キューと実行を処理するための素晴らしいライブラリである libuv です。
ノードは、既存の機能を実装するためにオペレーティング システム カーネルを可能な限り利用します。応答リクエストの生成、接続の転送、処理のためのシステムへの委託など。たとえば、着信接続は、Node で処理できるようになるまで、オペレーティング システムを通じてキューに入れられます。
Node にはスレッド プールがあると聞いたことがあるかもしれません。「Node がタスクを順番に処理するのに、なぜスレッド プールが必要なのでしょうか? これは、カーネル内ですべてのタスクが処理されるわけではないためです。」命令は非同期で実行されます。この場合、Node.JS は、ブロックされることなくイベント ループの実行を継続できるように、動作中にスレッドを一定期間ロックできる必要があります。
以下は、内部動作メカニズムを示す簡単な図の例です:
┌─────────────┐
╭─►│ タイマー タイマー
│ └───────┬───────┘
│ ┌───────┴───────┐
call係中のコールバック
│└。—七面
|
│ │ │ POLL ││── 接続、 │
│以来
│┌。—七面
╰─── ┤ setImmediate
━━━━━━━━━━┘
イベント ループの内部動作については、理解するのが難しい点がいくつかあります。
すべてのコールバックは、イベント ループ (タイマーなど) の 1 つのステージの終了時と次のステージに移行する前に、process.nextTick() を介してプリセットされます。これにより、無限ループを引き起こす process.nextTick() への再帰呼び出しの可能性が回避されます。
「保留中のコールバック」とは、他のイベント ループ サイクルによって処理されないコールバック キュー内のコールバック (たとえば、fs.write に渡される) です。
EventEmitter を作成することで、イベント ループとの対話を簡素化します。これは、イベントベースの API をより簡単に作成できるようにする汎用ラッパーです。この 2 つがどのように相互作用するかは、開発者を混乱させることがよくあります。
次の例は、イベントが同期的にトリガーされることを忘れると、イベントが見逃される可能性があることを示しています。
// v0.10 以降、require('events').EventEmitter は必要なくなりました
var EventEmitter = require('events');
var util = require('util');
関数 MyThing() {
EventEmitter.call(this);
doFirstThing();
this.emit('thing1');
}
util.inherits(MyThing, EventEmitter);
var mt = new MyThing();
mt.on('thing1', function onThing1() {
// 申し訳ありませんが、このイベントは決して発生しません
});
MyThing() はイベントをリッスンする前にインスタンス化する必要があるため、上記の「thing1」イベントは MyThing() によってキャプチャされることはありません。追加のクロージャを追加しない簡単な回避策は次のとおりです:
var EventEmitter = require('events');
var util = require('util');
関数 MyThing() {
EventEmitter.call(this);
doFirstThing();
setImmediate(emitThing1, this);
}
util.inherits(MyThing, EventEmitter);
関数 EmitThing1(self) {
self.emit('thing1');
}
var mt = new MyThing();
mt.on('thing1', function onThing1() {
// 実行されました
});
次のソリューションも機能しますが、パフォーマンスが多少犠牲になります:
function MyThing() {
EventEmitter.call(this);
doFirstThing();
// Function#bind() を使用するとパフォーマンスが低下します
setImmediate(this.emit.bind(this, 'thing1'));
}
util.inherits(MyThing, EventEmitter);
もう 1 つの問題は、エラーのトリガーです。アプリケーション内の問題を見つけるのは十分に困難ですが、コール スタック (*e.stack に注意) がなければ、デバッグはほぼ不可能です。リモートの非同期リクエストによって Error が受信されると、コール スタックが失われます。考えられる解決策は 2 つあります。同期的にトリガーするか、エラーが他の重要な情報と一緒に渡されるようにするかです。以下の例は両方の解決策を示しています:
MyThing.prototype.foo = function foo() {
// このエラーは非同期的にトリガーされます
var er = doFirstThing();
if (er) {
//トリガーされると、オンサイトのコールスタック情報を保持するために新しいエラーを作成する必要があります
setImmediate(emitError, this, new Error('Bad things'));
戻る;
}
// エラーをトリガーし、即座に (同期的に) 処理します
var er = doSecondThing();
if (er) {
This.emit('エラー', 'さらに悪いこと');
戻る;
}
}
状況を評価します。エラーが発生した場合、即座に対処できます。または、簡単に処理できる、または後で処理できる些細な例外である可能性があります。さらに、構築されたオブジェクト インスタンスが不完全である可能性が高いため、コンストラクターを介して Error を渡すことはお勧めできません。先ほど直接 Error がスローされた場合は例外です。
結論
この記事では、イベント ループの内部動作と技術的な詳細について簡単に説明します。それはすべてよく考えられています。別の記事では、イベント ループとシステム カーネルの相互作用について説明し、NodeJS の非同期操作の魅力を示します。

ホット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)

ホットトピック











ノンブロッキングおよびイベント駆動に基づいて構築されたノード サービスには、メモリ消費量が少ないという利点があり、大量のネットワーク リクエストの処理に非常に適しています。大量のリクエストを前提として、「メモリ制御」に関する問題を考慮する必要があります。 1. V8 のガベージ コレクション メカニズムとメモリ制限 Js はガベージ コレクション マシンによって制御されます

ファイル モジュールは、ファイルの読み取り/書き込み/開く/閉じる/削除の追加など、基礎となるファイル操作をカプセル化したものです。ファイル モジュールの最大の特徴は、すべてのメソッドが **同期** と ** の 2 つのバージョンを提供することです。 asynchronous**、sync サフィックスが付いているメソッドはすべて同期メソッドであり、持たないメソッドはすべて異種メソッドです。

当初、JS はブラウザ側でのみ動作していたため、Unicode でエンコードされた文字列の処理は簡単でしたが、バイナリ文字列や非 Unicode エンコード文字列の処理は困難でした。バイナリは、コンピュータのビデオ/オーディオ/プログラム/ネットワーク パッケージの最低レベルのデータ形式です。

スレッド プールを使用して Java7 でタスクの循環スケジューリングを実装する方法 はじめに: Java アプリケーションを開発する場合、スレッド プールを使用すると、タスクの実行効率とリソース使用率を向上させることができます。 Java7 では、スレッド プールを使用してタスクの循環スケジューリングを簡単に実装できます。この記事では、スレッド プールを使用して Java7 でタスクの循環スケジューリングを実装する方法を紹介し、対応するコード例を添付します。 1. 概要: スレッド プールは、固定数のスレッドを再利用して頻繁な作成やスレッドの作成を回避できるマルチスレッド処理構造です。

Linux は、サーバー システムで広く使用されている優れたオペレーティング システムです。 Linux システムを使用するプロセスでは、サーバー負荷の問題がよく発生します。サーバー負荷とは、サーバーのシステム リソースが現在の要求を満たすことができず、システム負荷が高くなりすぎて、サーバーのパフォーマンスに影響を与えることを意味します。この記事では、Linux システムにおける一般的なサーバー負荷の問題とその解決策を紹介します。 1. CPU 負荷が高すぎる サーバーの CPU 負荷が高すぎると、システムの応答が遅くなったり、リクエストの処理時間が長くなるなどの問題が発生します。 Cの場合

PHP8.0 のイベント処理ライブラリ: Event インターネットの継続的な発展に伴い、PHP は人気のバックエンド プログラミング言語として、さまざまな Web アプリケーションの開発に広く使用されています。このプロセスでは、イベント駆動のメカニズムが非常に重要な部分になっています。 PHP8.0 のイベント処理ライブラリ Event は、より効率的で柔軟なイベント処理メソッドを提供します。イベント処理とは何ですか? イベント処理は、Web アプリケーションの開発において非常に重要な概念です。イベントは任意の種類のユーザー行にすることができます

スレッド プールを使用して Java7 でタスク優先度スケジューリングを実装する方法 並行プログラミングでは、タスク優先度スケジューリングは一般的な要件です。 Java は、タスクを簡単に管理およびスケジュールできるようにするスレッド プール メカニズムを提供します。この記事では、スレッドプールを使用してJava7でタスク優先度スケジューリングを実装する方法を紹介します。まず、Java7 のスレッド プールの基本概念と使用法を理解する必要があります。スレッド プールは、複数のタスクを実行するスレッドのグループを管理およびスケジュールするスレッド再利用メカニズムです。 Java についての言及

JS-Torch の概要 JS-Torch は、構文が PyTorch に非常に似ている深層学習 JavaScript ライブラリです。これには、完全に機能するテンソル オブジェクト (追跡された勾配で使用可能)、深層学習レイヤーと関数、および自動微分エンジンが含まれています。 JS-Torch は JavaScript での深層学習の研究に適しており、深層学習の開発を加速するための便利なツールや機能を多数提供します。 Image PyTorch は、Meta の研究チームによって開発および保守されているオープンソースの深層学習フレームワークです。ニューラル ネットワーク モデルを構築およびトレーニングするための豊富なツールとライブラリのセットを提供します。 PyTorch は、シンプル、柔軟、そして使いやすいように設計されており、その動的な計算グラフ機能により、
