Events NodeJ在事件发出时等待回调完成

Events NodeJ在事件发出时等待回调完成,events,node.js,express,eventemitter,Events,Node.js,Express,Eventemitter,我已经用Express用NodeJS编写了一个插件和应用程序,我正试图使用EventEmitter创建一种插件体系结构,插件通过监听发出的事件连接到主代码中 当一个插件函数发出一个异步请求(在本例中是从mongo获取数据)时,我的问题就出现了。这会导致插件代码完成并将控制权返回给原始发射器,然后发射器将在插件代码中的异步请求完成之前完成执行 例如: 主应用程序: // We want to modify the request object in the plugin self.emit('

我已经用Express用NodeJS编写了一个插件和应用程序,我正试图使用EventEmitter创建一种插件体系结构,插件通过监听发出的事件连接到主代码中

当一个插件函数发出一个异步请求(在本例中是从mongo获取数据)时,我的问题就出现了。这会导致插件代码完成并将控制权返回给原始发射器,然后发射器将在插件代码中的异步请求完成之前完成执行

例如:

主应用程序:

// We want to modify the request object in the plugin  
self.emit('plugin-listener', request);
插件:

// Plugin function listening to 'plugin-listener', 'request' is an arg
console.log(request);

// Call to DB (async)
this.getFromMongo(some_data, function(response){
    // this may not get called until the plugin function has finished!
}
我之所以避免使用“getFromMongo”函数返回主代码的回调函数,是因为可能有0个或多个插件在侦听该事件。理想情况下,我希望在将控制权返回到主应用程序之前,能够以某种方式等待DB的工作完成


非常感谢

使用EventEmitter进行插件/中间件管理并不理想,因为如果侦听器具有异步代码,则无法确保它们按顺序执行。当这些侦听器彼此交互或使用相同的数据时,这尤其是一个问题


这就是为什么connect/express中间件函数存储在一个数组中并一个接一个地执行,而不是使用EventEmitter;他们每个人都需要调用next();当他们完成任务时函数。

不能将异步调用与同步行为混合使用。如果你打算坚持使用事件发射器(正如Klovadis所指出的,这可能不适合你),你需要让你的插件发出一个事件,触发主应用程序中的一个函数,其中包含你想要“等待”执行的代码。您还必须跟踪您正在等待事件调用的所有插件调用,以便在所有插件调用完成MongoDB回调之前,主代码不会运行

var callList = ['pluginArgs1', 'pluginArgs2', 'pluginArgs3'];
for (var i = 0; i < callList.length; i++){
  self.emit('plugin-listener', callList[i], i);
}

self.on('plugin-callback', function(i){
  callList.splice(i, 1);
  if (callList.length < 1){
    //we're done, do something
  }
});
var callList=['pluginArgs1','pluginArgs2','pluginArgs3'];
对于(var i=0;i
我自己还没有尝试过,但您可以使用事件数据对象中的属性作为函数数组,由发出事件的代码执行:

听众

foo.on('your-event', function(data) {
  console.log(data);
  // Then add the asynchronous code to a callbacks array
  // in the event data object
  data.callbacks.push(function(next) {
    getFromMongo(some_data, function(err, result) { next(err) }
  }
});
发射器

self.emit('your-event', data);
// listeners have modified data object,
// some might have added callback to data.callbacks
// (suppose you use async)
async.series(data.callbacks);

在将响应返回给客户机之前,我有时需要等待一些事件,有时则不需要等待(当不在HTTP请求上下文中时)

对我来说,最简单的方法是添加回调作为事件的最后一个参数

Stuff.emit('do_some_stuff', data, data2, callback);
在事件中,检查是否存在回调:

Stuff.on('do_some_stuff', function(data, data2, callback) {
  // stuff to do
  // ...
  if (typeof callback === "function") return callback(err, result);
});
我知道混合事件和回调可能会很混乱,但这对于我所需要的工作来说很好。
我看到的另一个解决方案是@redben提出的:在事件末尾添加一个emit函数。在HTTP上下文中的问题是,您需要唯一的密钥,这样,如果事件针对每个用户执行不同的操作,那么事件就不会出错

这似乎很危险,但无论如何我都得这么做

constee=neweventemitter();
if(ee.listeners(“异步事件”).length>0){
等待新的承诺((决心)=>{
ee.emit(“异步事件”、数据1、数据2、解析);
});
}

否则,只需来回发送事件。

如果事件有多个侦听器,则此方法不起作用。方法是从侦听器发送一个新的事件并等待它