ホームページ > ウェブフロントエンド > jsチュートリアル > ノードイベントの仕組みの説明

ノードイベントの仕組みの説明

小云云
リリース: 2018-01-26 13:31:34
オリジナル
1526 人が閲覧しました

この記事では主にノードのイベントメカニズムを紹介し、EventEmitterクラスの実装アイデアを明確にするために簡単なイベントメカニズムを実装します。

Node.js はイベント駆動型のノンブロッキング I/O モデルを使用しており、軽量かつ効率的です。

nodejs の公式ドキュメントには、node の機能の 1 つがイベントであると明確に書かれています。駆動 (イベント ドライバー) が非常に重要であることがわかります。ソース コードを見ると、そのイベント メカニズムは js で記述された EventEmitter クラスであることがわかります。これは非常にエレガントに記述されており、パブリッシュ/サブスクライブ モデルを適用しています。

パブリッシュ/サブスクライブ モードで単純なイベント メカニズムを実装することで、EventEmitter クラスの実装アイデアを明確にすることができます

Publish/Subscribe (パブリッシュ/サブスクライブ モード)

類似点

はパターン、つまり単語のパターンに関するものです、非常に抽象的に聞こえます。まずは栗をあげましょう。朝、昼、夕刊を発行する新聞組織があるとします。特定の新聞を読みたい場合は、新聞社に購読する必要があります。該当する新聞が発売されると、新聞社から新聞を受け取るように通知されます。

このプロセスにおいて、新聞組織は 2 つの機能を実装しました。1 つは顧客の購読を受け入れることで、もう 1 つはさまざまな種類の新聞を発行することです。新聞が発行されると、その種類の新聞を購読している顧客に通知が届きます。

この新聞組織は私たちが実現したいイベントの仕組みです。

目的

上記の例からわかるように、1. 新聞を発行します。2. 新聞組織の存在により、この継続的なプロセスが最初に購読されます。公開すると、リリース時に自動的に顧客に送信され、アクション時間の分離が実現します。これはパブリッシュ/サブスクライブ システムの利点でもあります。

実装アイデア

3つのイベントに対応した3種類の新聞があり、それぞれのイベントが発生したときに顧客に通知する必要があります。対応するデータ形式は次のとおりです:


var Event = {
 morning: event1,
 noon: event2,
 night: event3
}
ログイン後にコピー

各新聞は複数の人が購読している可能性があるため、形式は次のように最適化できます:


var Event = {
 morning: [e11, e12,...],
 noon: [e21, e22],
 night: event3
}
ログイン後にコピー

ユーザーが購読すると、イベントは対応する配列に追加され、イベントが解放されると、対応するイベントが実行されます。はっきり言って、保管してから使いましょう。

具体的なコードは次のとおりです:

1.on はサブスクライブを意味し、対応する配列にイベントを追加します
2.emit はパブリッシュを意味し、対応する配列内のデータを実行のために取り出します
3.off は無駄なイベントを削除することを意味します


var Event = {
 on: function(key, listener) {
  if (!this.__events) {
   this.__events = {}
  }
  if (!this.__events[key]) {
   this.__events[key] = [];
  } 
  if (_indexOf(this.__events[key], listener) == -1 && typeof listener === 'function') {
   this.__events[key].push(listener)
  }
 },
 emit: function(key) {
  if (!this.__events || !this.__events[key]) return 
  //取得每次订阅不同的参数
  var arg = Array.prototype.slice.call(arguments, 1) || [];

  var listeners = this.__events[key];
  var len = listeners.length;

  for (var i=0; i<len; i++) {
   listeners[i].apply(this, arg)
  }
  return this

 },
 off: function(key, listener) {
  if (!key && !listener) {
   this.__events = {}
  }
  if (key && !listener) {
   delete this.__events[key]
  }
  if (key && listener) {
   var listeners = this.__events[key];
   var index = _indexOf(listeners, listener);
   (index > -1) && listeners.splice(index, 1);
  }
  return this
 }
}

var _indexOf = function(array,key){
 if (array === null) return -1
 var i = 0, length = array.length
 for (; i < length; i++) if (array[i] === key) return i
 return -1
}
//调用
Event.on(&#39;console1&#39;, function(num) {
 console.log(num); // 1
});

Event.emit(&#39;console1&#39;, 1)
ログイン後にコピー

ノードのEventEmitter

ノードのEventEmitterの基本ロジックは、上記の例と基本的に同じですが、より複雑です。

1. イベントを購読する


function _addListener(target, type, listener, prepend) {
 var m;
 var events;
 var existing;

 if (typeof listener !== &#39;function&#39;)
  throw new TypeError(&#39;"listener" argument must be a function&#39;);

 events = target._events;
 ...
 if (typeof existing === &#39;function&#39;) {
   // Adding the second element, need to change to array.
   existing = events[type] =
    prepend ? [listener, existing] : [existing, listener];
  } else {
   // If we&#39;ve already got an array, just append.
   if (prepend) {
    existing.unshift(listener);
   } else {
    existing.push(listener);
   }
  }

 return target;
}

EventEmitter.prototype.addListener = function addListener(type, listener) {
 return _addListener(this, type, listener, false);
};

EventEmitter.prototype.on = EventEmitter.prototype.addListener;
ログイン後にコピー

2. イベントを公開する


EventEmitter.prototype.emit = function emit(type) {
 ...
 handler = events[type];
 switch (len) {
  // fast cases
  case 1:
   emitNone(handler, isFn, this);
   break;
  case 2:
   emitOne(handler, isFn, this, arguments[1]);
   break;
  case 3:
   emitTwo(handler, isFn, this, arguments[1], arguments[2]);
   break;
  case 4:
   emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
   break;
  // slower
  default:
   args = new Array(len - 1);
   for (i = 1; i < len; i++)
    args[i - 1] = arguments[i];
   emitMany(handler, isFn, this, args);
 }
}
ログイン後にコピー

ここまで述べて、皆さんは EventEmitter の実装アイデアを理解できたと思います。

関連する推奨事項:

PHPイベントメカニズムの実装

jqおよびjsでのイベントメカニズムとブロック

JavaScriptイベントメカニズム

以上がノードイベントの仕組みの説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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