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

时间:2016-05-15 05:49:42

标签: javascript node.js sockets module

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

节点服务器:

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

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

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

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

server.js

socket

module.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;

此外,当我尝试使用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

2 个答案:

答案 0 :(得分:19)

在node.js中,EventEmitter object通常是您想要创建具有事件侦听器然后可以触发事件的对象时使用的内容。您可以直接使用public class ActivityProductList extends AppCompatActivity { private android.support.v7.widget.SearchView searchView = null; private RecyclerView recyclerView; MyAdapter adapter; List<ParentListItem> parentListItems = new ArrayList<>(); List<ParentListItem> originalProductList = new ArrayList<>(); String query = null; int categoryId = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_products_final); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setTitle("PRODUCTS"); getSupportActionBar().setDisplayHomeAsUpEnabled(true); //ViewPager viewPager = (ViewPager) findViewById(R.id.pager); TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); tabLayout.addTab(tabLayout.newTab().setText("Tab 1")); tabLayout.addTab(tabLayout.newTab().setText("Tab 2")); //setupViewPager(viewPager); //tabLayout.setupWithViewPager(viewPager); //viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); searchView = (android.support.v7.widget.SearchView) findViewById(R.id.searchView); searchView.setIconified(false); searchView.onActionViewExpanded(); searchView.clearFocus(); searchView.setOnQueryTextListener(new android.support.v7.widget.SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { if (adapter != null) filterData(query); return false; } @Override public boolean onQueryTextChange(String query) { if (adapter != null) filterData(query); return false; } }); } } 对象,也可以从中派生并创建自己的具有所有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);

这里的关键点是:

  1. 如果您希望模块允许人们监听事件然后触发事件,您可能想要创建// module2.js var m1 = require('module1.js'); // register event listener m1.on("someEvent", function(data) { // process data when someEvent occurs }); 对象。
  2. 要共享该EventEmitter个对象,请将其分配给EventEmittermodule.exports的属性,以便执行模块module.exports的其他代码可以访问require()对象。
  3. 一旦调用代码从EventEmitter获取EventEmitter对象,它就可以注册以使用require()方法监听事件。
  4. 当原始模块或任何模块想要触发事件时,可以使用.on()方法执行此操作。
  5. 请记住,有时事件是一个很好的架构选择,但并非模块之间的所有通信都最适合事件。有时,只导出函数并允许一个模块调用另一个模块的函数是有意义的。因此,事件不是模块可以相互通信的唯一方式。

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

答案 1 :(得分:3)

为了让我更轻松,我创建了一个名为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')