如何在JavaScript模块文件与Node.js之间使用事件处理程序?

时间:2020-12-14 23:57:43

I'm currently using socket.io to emit and listen to events between a client-side JavaScript file and a Node.js server file, but I'd like to be able to emit and listen to events between the Node server and its modules. My thought is that it would look something like this:

我目前正在使用socket.io来发出和侦听客户端JavaScript文件和Node.js服务器文件之间的事件,但我希望能够发出和侦听节点服务器及其模块之间的事件。我的想法是它看起来像这样:

Node server:

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
}

Module file:

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

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

This is obviously a simplified version but I would think that this functionality should be available. Do I need to set up the module file as a second server? If so, what would that look like?

这显然是一个简化版本,但我认为这个功能应该可用。我是否需要将模块文件设置为第二台服务器?如果是这样,那会是什么样子?

I also tried using var socket = io.connect('http://localhost:3000'); (this is the code I use to allow the client to connect to the Node server) instead of server and had module1 listen on and emit to socket but that didn't work either.

我也尝试使用var socket = io.connect('http:// localhost:3000'); (这是我用来允许客户端连接到节点服务器的代码)而不是服务器,并且让module1监听并发送到套接字,但这也不起作用。

SECOND ATTEMPT (still not working):

第二次尝试(仍然没有工作):

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;

Also, when I try to use server1.on, I get the message server1.on is not a function.

此外,当我尝试使用server1.on时,我收到消息server1.on不是一个函数。

2 个解决方案

#1


17  

In node.js, the EventEmitter object is typically what you use if you want to create an object that has event listeners and can then trigger events. You can either use the EventEmitter object directly or you can derive from it and create your own object that has all the EventEmitter functionality.

在node.js中,如果要创建具有事件侦听器然后可以触发事件的对象,则通常使用EventEmitter对象。您可以直接使用EventEmitter对象,也可以从中派生并创建自己的具有所有EventEmitter功能的对象。

So, if you wanted to create a module that other modules could listen for events on, you would do something like this:

所以,如果你想创建一个其他模块可以监听事件的模块,你可以这样做:

// 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);

Then, you could have another module that uses that first one and listens for some events coming from it:

然后,您可以使用另一个使用第一个模块的模块并侦听来自它的一些事件:

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

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

The key points here are:

这里的关键点是:

  1. If you want a module to allow people to listen for events and to then trigger events, you probably want to create an EventEmitter object.
  2. 如果您希望模块允许人们监听事件然后触发事件,您可能想要创建一个EventEmitter对象。

  3. To share that EventEmitter object, you assign it to module.exports or a property of module.exports so that other code that does a require() of your module can get access to the EventEmitter object.
  4. 要共享该EventEmitter对象,请将其分配给module.exports或module.exports的属性,以便执行模块require()的其他代码可以访问EventEmitter对象。

  5. Once the calling code gets the EventEmitter object from the require(), it can then register to listen for events with the .on() method.
  6. 一旦调用代码从require()获取EventEmitter对象,它就可以注册以使用.on()方法监听事件。

  7. When the original module or any module wants to trigger an event, it can do so with the .emit() method.
  8. 当原始模块或任何模块想要触发事件时,它可以使用.emit()方法执行此操作。


Keep in mind that sometimes events are a great architectural choice, but not all communication between modules is best suited to events. Sometimes, it makes sense to just export functions and allow one module to call another module's functions. So, events are not the only way that modules can communicate with one another.

请记住,有时事件是一个很好的架构选择,但并非模块之间的所有通信都最适合事件。有时,只导出函数并允许一个模块调用另一个模块的函数是有意义的。因此,事件不是模块可以相互通信的唯一方式。


Your question seems to indicate that you think of socket.io as a way for two modules in the same server process to communicate. While it might be possible to do that, that is not normally how socket.io would be used. Usually socket.io (which is TCP/IP based) would be used for communicating between two separate processes where you do not have the luxury of making a direct function call or registering a handler for an event within your process. These latter two schemes are typically much easier for communication within a process, whereas socket.io is more typically use for communication between processes on the same computer or between processes on different computers.

您的问题似乎表明您认为socket.io是同一服务器进程中两个模块进行通信的一种方式。虽然有可能这样做,但通常不会使用socket.io。通常,socket.io(基于TCP / IP)将用于两个独立进程之间的通信,在这两个进程中,您无需进行直接函数调用或为进程中的事件注册处理程序。后两种方案通常更容易在进程内进行通信,而socket.io更常用于同一计算机上的进程之间或不同计算机上的进程之间的通信。

#2


2  

To make this easier for me, I created a new js file called Notifier.js which looks like this:

为了让我更容易,我创建了一个名为Notifier.js的新js文件,如下所示:

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

When I want to use the emitter I simple require the Notifier.js file and access the exported value. e.g.

当我想使用发射器时,我需要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')

#1


17  

In node.js, the EventEmitter object is typically what you use if you want to create an object that has event listeners and can then trigger events. You can either use the EventEmitter object directly or you can derive from it and create your own object that has all the EventEmitter functionality.

在node.js中,如果要创建具有事件侦听器然后可以触发事件的对象,则通常使用EventEmitter对象。您可以直接使用EventEmitter对象,也可以从中派生并创建自己的具有所有EventEmitter功能的对象。

So, if you wanted to create a module that other modules could listen for events on, you would do something like this:

所以,如果你想创建一个其他模块可以监听事件的模块,你可以这样做:

// 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);

Then, you could have another module that uses that first one and listens for some events coming from it:

然后,您可以使用另一个使用第一个模块的模块并侦听来自它的一些事件:

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

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

The key points here are:

这里的关键点是:

  1. If you want a module to allow people to listen for events and to then trigger events, you probably want to create an EventEmitter object.
  2. 如果您希望模块允许人们监听事件然后触发事件,您可能想要创建一个EventEmitter对象。

  3. To share that EventEmitter object, you assign it to module.exports or a property of module.exports so that other code that does a require() of your module can get access to the EventEmitter object.
  4. 要共享该EventEmitter对象,请将其分配给module.exports或module.exports的属性,以便执行模块require()的其他代码可以访问EventEmitter对象。

  5. Once the calling code gets the EventEmitter object from the require(), it can then register to listen for events with the .on() method.
  6. 一旦调用代码从require()获取EventEmitter对象,它就可以注册以使用.on()方法监听事件。

  7. When the original module or any module wants to trigger an event, it can do so with the .emit() method.
  8. 当原始模块或任何模块想要触发事件时,它可以使用.emit()方法执行此操作。


Keep in mind that sometimes events are a great architectural choice, but not all communication between modules is best suited to events. Sometimes, it makes sense to just export functions and allow one module to call another module's functions. So, events are not the only way that modules can communicate with one another.

请记住,有时事件是一个很好的架构选择,但并非模块之间的所有通信都最适合事件。有时,只导出函数并允许一个模块调用另一个模块的函数是有意义的。因此,事件不是模块可以相互通信的唯一方式。


Your question seems to indicate that you think of socket.io as a way for two modules in the same server process to communicate. While it might be possible to do that, that is not normally how socket.io would be used. Usually socket.io (which is TCP/IP based) would be used for communicating between two separate processes where you do not have the luxury of making a direct function call or registering a handler for an event within your process. These latter two schemes are typically much easier for communication within a process, whereas socket.io is more typically use for communication between processes on the same computer or between processes on different computers.

您的问题似乎表明您认为socket.io是同一服务器进程中两个模块进行通信的一种方式。虽然有可能这样做,但通常不会使用socket.io。通常,socket.io(基于TCP / IP)将用于两个独立进程之间的通信,在这两个进程中,您无需进行直接函数调用或为进程中的事件注册处理程序。后两种方案通常更容易在进程内进行通信,而socket.io更常用于同一计算机上的进程之间或不同计算机上的进程之间的通信。

#2


2  

To make this easier for me, I created a new js file called Notifier.js which looks like this:

为了让我更容易,我创建了一个名为Notifier.js的新js文件,如下所示:

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

When I want to use the emitter I simple require the Notifier.js file and access the exported value. e.g.

当我想使用发射器时,我需要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')