Events NodeJ在事件发出时等待回调完成
我已经用Express用NodeJS编写了一个插件和应用程序,我正试图使用EventEmitter创建一种插件体系结构,插件通过监听发出的事件连接到主代码中 当一个插件函数发出一个异步请求(在本例中是从mongo获取数据)时,我的问题就出现了。这会导致插件代码完成并将控制权返回给原始发射器,然后发射器将在插件代码中的异步请求完成之前完成执行 例如: 主应用程序: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('
// 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、解析);
});
}
否则,只需来回发送事件。如果事件有多个侦听器,则此方法不起作用。方法是从侦听器发送一个新的事件并等待它