等待来自不同模块的多个事件,然后启动服务器

我正在构build一个应用程序,其中有两个不同的模块。其中一个是连接到mongodb,另一个模块是连接到redis进行会话pipe理。 在这种情况下,每个模块有2个事件错误和连接。 以下是其中一个模块的示例:

var sessionStore = new SessionStore(app.get("sessionStore")); sessionStore.client.on("error", function(err) { console.error("[SessionStore]:", "connection error:", err.address + ":" + err.port, "for process:", process.pid); var sessionStoreError = new Error("Session store error"); sessionStoreError.message = "Session store connection error"; sessionStoreError.code = err.code; sessionStoreError.address = err.address; sessionStoreError.port = err.port; app.emit("error", sessionStoreError); }); sessionStore.client.on("connect", function() { console.log("[SessionStore]:", "connection established:", app.get("sessionStore").host + ":" + app.get("sessionStore"), "for process:", process.pid); app.emit("ready"); }); 

与mongodb模块几乎一样。

我想实现的(避免厄运的金字塔)是这样的,但是当它们的模块的redis和mongodb连接成功时:

 app.on("ready", function(){ app.listen(app.get("port")); }); 

请记住,我可以将每个模块嵌套在另一个模块中,也许需要连接处理程序中的模块顺序排列,然后发出一个最终事件给应用程序,但根据我的口味,这不是优雅的。

有没有什么优雅的方式来等待2个事件,然后启动服务器?

bootable提供了一个初始化层,您也可以使用快速应用程序。 这并不严格地为您的问题( “等待2个事件” )提供解决scheme,但它确实解决了在启动服务器之前等待多个asynchronous模块的问题。

您可以为MongoDB和Redis添加启动阶段。 一旦所有阶段都准备好了, app.boot()的callback被调用(你可以检查是否有初始化错误),当一切正常时,应用程序可以开始监听传入的连接。

以下是您的会话存储示例转换为引导阶段:

 module.exports = function(app) { app.phase(function(done) { var sessionStore = new SessionStore(app.get("sessionStore")); sessionStore.client.once("error", function(err) { console.error("[SessionStore]:", "connection error:", err.address + ":" + err.port, "for process:", process.pid); var sessionStoreError = new Error("Session store error"); sessionStoreError.message = "Session store connection error"; sessionStoreError.code = err.code; sessionStoreError.address = err.address; sessionStoreError.port = err.port; return done(sessionStoreError); }); sessionStore.client.once("connect", function() { console.log("[SessionStore]:", "connection established:", app.get("sessionStore").host + ":" + app.get("sessionStore"), "for process:", process.pid); return done(); }); }); }; 

你的主代码看起来像这样:

 var bootable = require('bootable'); var express = require('express') var app = bootable(express()); require('./boot/session-store')(app); // loads the module above require('./boot/mongodb')(app); // a MongoDB boot phase // This is the equivalent of your `app.on('ready', ...)` app.boot(function(err) { if (err) throw err; app.listen(app.get("port")); }); 

从我的头顶来看,这是我能想到的最好的解决scheme:

我认为最“优雅”的方式,正如你所build议的,用async.waterfall调用每个模块,当它们都完成时,发送一个事件给应用程序。 我认为这是一个很好的解决scheme,但唯一的问题是,通过连续激活模块而不是同时激活模块会浪费时间。

为了节省时间,也许你可以使用一个不那么“优雅”的解决scheme:

redis模块将发出一个名为“redisReady”的事件,mongoDb模块会发出一个名为“mongoReady”的模块,在主模块中将会有:

 app.on("redisReady", function(){ redisModuleReady = true; if (mongoModuleReady) { app.listen(app.get("port")); } }); app.on("mongoReady", function(){ mongoModuleReady = true; if (redisModuleReady) { app.listen(app.get("port")); } }); 

这是不太“漂亮”,但节省时间。

当然有更多的解决scheme,但是这是我想出的。