web-dev-qa-db-ja.com

Node.jsでJavaScriptモジュールファイル間でイベントハンドラーを使用するにはどうすればよいですか?

現在、_socket.io_を使用して、クライアント側のJavaScriptファイルとNode.jsサーバーファイルの間でイベントを発行およびリッスンしていますが、Nodeサーバーとそのモジュール。私の考えでは、次のようになります。

ノードサーバー:

_var module1 = require('./module1');

//Some code to launch and run the server

module1.emit('eventToModule');
module1.emit('moduleResponse', function(moduleVariable) {
   //server action based on module response
}
_

モジュールファイル:

_var server = require('./server.js');

server.on('eventToModule', function() {
   //module response to server request
}
server.emit('moduleResponse', moduleVariable);
_

これは明らかに簡略化されたバージョンですが、この機能が利用できるはずだと思います。モジュールファイルを2番目のサーバーとして設定する必要がありますか?もしそうなら、それはどのように見えるでしょうか?

また、serverの代わりにvar socket = io.connect('http://localhost:3000');(これは、クライアントがNodeサーバーに接続できるようにするために使用するコードです)を使用してみましたが、_module1_がありました。聞いてsocketに送信しますが、それも機能しませんでした。

2回目の試行(まだ機能していません):

server.js

_//other requirements
var module1 = require('./module');
const EventEmitter = require('events');
var emitter = new EventEmitter();

io.on('connection', function(client) {
   client.on('emitterTester', function() {
      emitter.emit('toModule');
      emitter.on('toServer', function() {
         console.log("Emitter successful.");
      });
   });
});

module.exports = emitter;
_

module.js

_var server1 = require('./server');
const EventEmitter = require('events');
var emitter = new EventEmitter();

emitter.on('toModule', function() {
   console.log("Emitter heard by module.");
   emitter.emit('toServer');         
});

module.exports = emitter;
_

また、_server1.on_を使おうとすると、_server1.on is not a function_というメッセージが表示されます。

8
SuperCodeBrah

Node.jsでは、 EventEmitter object は通常、イベントリスナーを持ち、イベントをトリガーできるオブジェクトを作成する場合に使用します。 EventEmitterオブジェクトを直接使用することも、それから派生してすべてのEventEmitter機能を備えた独自のオブジェクトを作成することもできます。

したがって、他のモジュールがイベントをリッスンできるモジュールを作成する場合は、次のようにします。

_// module1.js
// module that has events

// create EventEmitter object
var obj = new EventEmitter();

// export the EventEmitter object so others can use it
module.exports = obj;

// other code in the module that does something to trigger events
// this is just one example using a timer
setInterval(function() {
    obj.emit("someEvent", someData);
}, 10 * 1000);
_

次に、その最初のモジュールを使用して、そこから発生するいくつかのイベントをリッスンする別のモジュールを作成できます。

_// module2.js
var m1 = require('module1.js');

// register event listener
m1.on("someEvent", function(data) {
    // process data when someEvent occurs
});
_

ここでの重要なポイントは次のとおりです。

  1. 人々がイベントをリッスンしてからイベントをトリガーできるようにするモジュールが必要な場合は、おそらくEventEmitterオブジェクトを作成する必要があります。
  2. そのEventEmitterオブジェクトを共有するには、それを_module.exports_または_module.exports_のプロパティに割り当てて、モジュールのrequire()を実行する他のコードがアクセスできるようにします。 EventEmitterオブジェクト。
  3. 呼び出し元のコードがrequire()からEventEmitterオブジェクトを取得すると、.on()メソッドを使用してイベントをリッスンするように登録できます。
  4. 元のモジュールまたは任意のモジュールがイベントをトリガーする場合は、.emit()メソッドを使用してトリガーできます。

イベントが優れたアーキテクチャ上の選択である場合もありますが、モジュール間のすべての通信がイベントに最適であるとは限らないことに注意してください。関数をエクスポートして、あるモジュールが別のモジュールの関数を呼び出せるようにすることが理にかなっている場合があります。したがって、モジュールが相互に通信できる方法はイベントだけではありません。


あなたの質問は、socket.ioを同じサーバープロセス内の2つのモジュールが通信する方法として考えていることを示しているようです。それは可能かもしれませんが、それは通常、socket.ioが使用される方法ではありません。通常、socket.io(TCP/IPベース)は、直接関数呼び出しを行ったり、プロセス内のイベントのハンドラーを登録したりする余裕がない2つの別々のプロセス間の通信に使用されます。これらの後者の2つのスキームは、通常、プロセス内の通信にはるかに簡単ですが、socket.ioは、通常、同じコンピューター上のプロセス間または異なるコンピューター上のプロセス間の通信に使用されます。

24
jfriend00

これを簡単にするために、次のようなNotifier.jsという新しいjsファイルを作成しました。

let EventEmitter = require('events').EventEmitter
let notifier = new EventEmitter()
module.exports = notifier

エミッターを使用したい場合は、Notifier.jsファイルが必要で、エクスポートされた値にアクセスします。例えば.

randomFile.js

var notifier = require('Notifier.js')
notifier.on('myEvent', (message) => {
    console.log(message)
})

randomFile2.js

var notifier = require('Notifier.js')
notifier.emit('myEvent', 'Test Message')
7
Matthew Cawley