Node.jsのイベントループとコールバック関数についての深い理解

高洛峰
リリース: 2016-12-08 10:26:53
オリジナル
1475 人が閲覧しました

この記事では、Node.js イベント ループと Node.js コールバック関数について詳しく説明します。詳細については、以下を参照してください。

1. Node.js イベント ループ

Node.js は単一プロセス、単一スレッドのアプリケーションですが、イベントとコールバックによる同時実行をサポートしているため、パフォーマンスは非常に高くなります。 Node.js のすべての API は非同期であり、別個のスレッドとして実行され、非同期関数呼び出しを使用し、同時実行を処理します。基本的に、Node.js のすべてのイベント メカニズムは、デザイン パターンのオブザーバー パターンを使用して実装されます。 Node.js の単一スレッドは、イベント オブザーバーが終了するまで while(true) イベント ループに入るのと似ています。イベントが発生すると、コールバック関数が呼び出されます。


Node.js はイベント駆動型モデルを使用し、Web サーバーがリクエストを受信すると、リクエストを閉じて処理し、次の Web リクエストを処理します。リクエストが完了すると、リクエストは処理キューに戻され、キューの先頭に達すると結果がユーザーに返されます。このモデルは、Web サーバーが読み取りまたは書き込み操作を待たずに常にリクエストを受け入れるため、非常に効率的でスケーラブルです。 (これは、ノンブロッキング IO またはイベント駆動型 IO とも呼ばれます)。イベント駆動型モデルでは、イベントをリッスンし、イベントが検出されたときにコールバック関数をトリガーするメイン ループが生成されます。


イベント駆動型プロセス全体はこのように非常に簡単に実装されます。オブザーバー パターンとある程度似ており、イベントはサブジェクト (Subject) に相当し、このイベントに登録されたすべてのハンドラー関数はオブザーバー (Observer) に相当します。 Node.js には複数の組み込みイベントがあります。以下に示すように、イベント モジュールを導入して EventEmitter クラスをインスタンス化することで、イベントをバインドしてリッスンできます。 例


js を作成します。ファイルのコードは次のとおりです。

// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
以下程序绑定事件处理程序:
// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandler);
我们可以通过程序触发事件:
// 触发事件
eventEmitter.emit('eventName');
ログイン後にコピー


2. Node.js コールバック関数

Node.js 非同期プログラミングの直接的な表現はコールバックです。非同期プログラミングはコールバックに依存しますが、コールバックを使用したからといってプログラムが非同期になるとは言えません。コールバック関数は、タスクの完了後に呼び出されます。すべてのノード API はコールバック関数をサポートしています。たとえば、他のコマンドの実行中にファイルを読み取ることができます。ファイルの読み取りが完了したら、ファイルの内容をコールバック関数のパラメーターとして返します。これにより、コードの実行中にファイル I/O 操作がブロックされたり、待機したりすることがなくなります。これにより、Node.js のパフォーマンスが大幅に向上し、多数の同時リクエストを処理できるようになります。

1. ブロック コードの例

次の内容のファイル test.txt を作成します:

// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
// 创建事件处理程序
var connectHandler = function connected() {
  console.log('连接成功。');
  // 触发 data_received 事件
  eventEmitter.emit('data_received');
}
// 绑定 connection 事件处理程序
eventEmitter.on('connection', connectHandler);
// 使用匿名函数绑定 data_received 事件
eventEmitter.on('data_received', function(){
  console.log('数据接收成功。');
});
// 触发 connection 事件
eventEmitter.emit('connection');
console.log("程序执行完毕。");
ログイン後にコピー

次のコードを含む test.js ファイルを作成します:

Hello World!
fs.readFileSync()
fs.readFile()
ログイン後にコピー

上記のコードの実行結果は次のとおりです:

2. ノンブロッキング コードの例

test.js ファイルを作成します。コードは次のとおりです:

console.log('-------程序开始执行--------'); 
// 引入fs模块
var fs = require("fs");
//同步读取文件
var data = fs.readFileSync('test.txt','utf-8');
console.log(data.toString());
console.log('-------程序执行结束--------');
ログイン後にコピー


上記のプログラムでは、fs.readFile() は非同期です。ファイルを読み取るために使用される関数。ファイルの読み取り中にエラーが発生した場合、error err オブジェクトはエラー情報を出力します。エラーが発生しない場合、readFile は err オブジェクトの出力をスキップし、ファイルの内容はコールバック関数を通じて出力されます。

上記のコードの実行結果は次のとおりです。

次に input.txt ファイルを削除します。実行結果は次のとおりです。

上記 2 つの例では、ブロック呼び出しと非ブロック呼び出しの違いがわかります。最初のインスタンスは、ファイルの読み取り後にプログラムの実行を終了します。 2 番目の例では、ファイルが読み取られるのを待つ必要がないため、ファイルの読み取りと同時に次のコードを実行できるため、プログラムのパフォーマンスが大幅に向上します。したがって、ブロッキングは順番に実行されますが、ノンブロッキングは順番に実行する必要がないため、コールバック関数のパラメータを処理する必要がある場合は、コールバック関数内に記述する必要があります。

3. fs.readFileSync と fs.readFile

1. s.readFileSync

構文: fs.readFileSync(filename, [encoding])

受信パラメータ:

ファイル名: ファイルパス

オプション: オプションオブジェクト、エンコード、エンコード形式を含む、この項目はオプションです。

Node.js は、utf8、ucs2、ascii、binary、base64、hex のエンコーディングのみをサポートしているため、中国語の GBK や GB2312 などのエンコーディングはサポートしていないため、ファイルの中国語のコンテンツを読み書きしたい場合は、 GBK または GB2312 形式。追加モジュール iconv-lite を使用する必要があります。

2. fs.readFile

構文: fs.readFile(filename, [encoding], [callback(err,data)])

受信パラメータ:

ファイル名: ファイルパス

オプション: エンコーディングを含むオプションオブジェクト、エンコード形式、この項目はオプションです。

コールバック: コールバック、2 つのパラメーター: 例外エラーとファイル コンテンツ データを渡します

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!