NodeJS等待callback完成事件发射

我有和应用程序写在NodeJS与Express,并试图使用EventEmitter来创build一种插件体系结构,通过侦听发出的事件插入到主代码的插件。

我的问题是当一个插件函数发出一个asynchronous请求(在这种情况下从mongo获取数据)时,这会导致插件代码完成并返回到原始发射器,然后在插件代码中的asynchronous请求之前完成执行饰面。

例如:

主应用程序:

// 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”函数回避主要代码的callback函数的原因是可能有0个或多个插件监听事件。 理想情况下,我想要一些方法来等待数据库的东西完成,然后返回到主应用程序的控制

非常感谢

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

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

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

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

对于某些事件做出同样的决定,我有时需要等待,直到返回响应给客户端,有时甚至不需要(当不在HTTP请求上下文中)。

对我来说最简单的方法就是添加callback作为事件的最后一个参数。

 Stuff.emit('do_some_stuff', data, data2, callback); 

在事件中检查是否有callback:

 Stuff.on('do_some_stuff', function(data, data2, callback) { // stuff to do // ... if (typeof callback === "function") return callback(err, result); }); 

我知道混合事件和callback可能是混乱的,但是这对我所需要的工作很好。 我看到的另一个解决scheme是由@redben提出的:在事件结束处添加一个emit函数。 在HTTP上下文中的问题是你需要唯一的密钥,这样你的事件不会搞乱每个用户做不同的事情。

还没有自己尝试过,但是你可以在事件的数据对象中使用一个属性作为一个函数的数组,通过发出事件的代码来执行:

听众

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