2015-12-02 19 views
1

我正在構建一個應用程序,其中有兩個不同的模塊。其中一個是與mongodb的連接,另一個模塊是連接到redis以進行會話管理。在這種情況下,每個模塊都有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個事件,然後啓動服務器?

+0

你應該檢查的承諾,並等待使用承諾所有的承諾。所有(promisesArray) – mkinawy

回答

1

bootable提供了一個初始化層,您也可以將其用於Express應用程序。這並不嚴格爲您的問題提供解決方案(「等待2個事件」),但它確實解決了在啓動服務器之前等待多個異步模塊的問題。

您可以爲MongoDB和Redis添加啓動階段。一旦所有階段都準備好了,回調到app.boot()就會被調用(您可以檢查那裏的任何初始化錯誤),當一切正常時,應用程序可以開始監聽傳入連接。

這是你的會話存儲例如變成了啓動階段:

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

從我的頭頂,這是我能想到的最好的解決辦法:

我覺得最「優雅」的方式是,像你這樣的建議,打電話與async.waterfall每個模塊,當他們都完成了,發送一個事件給應用程序。我認爲這是一個很好的解決方案,但唯一的問題是,通過連續激活模塊而不是同時激活模塊會浪費時間。

爲了節省時間,也許你可以使用這樣一個不太「優雅」的解決方案:

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

這很不「漂亮」,但節省時間。

當然還有更多的解決方案,但這是我想出的。

+0

是啊,我想這樣的事情太多,這是可悲的壽,有一個內置的方法Eventemitter從多個這樣的活動情況 – Syd

+0

'重新權利,I've搜查,一無所獲,雖然這是一個合理的特點。如果有isn't東西I've錯過了,我想我的答案是最好的一段路要走。 –

相關問題