2013-03-22 3 views
7

Ich habe eine Middleware für Connect und Express geschrieben, die in ihrer Einrichtungsmethode etwas schweres Heben erfordert. Aufgrund der Art der Initialisierungs-Tasks ist dieses Zeug asynchron, so dass ich das Problem habe, dass die Middleware nur zugänglich sein sollte, sobald die Initialisierung ausgeführt wurde.Wie verwendet man asynchrone Initialisierung in einer Connect Middleware?

Zur Zeit habe ich es mit einem Rückruf gelöst:

function setupMiddleware(callback) { 
    doSomeAsyncInitialization(function() { 
    callback(function (req, res, next) { 
     // The actual middleware goes here ... 
    }); 
    }); 
} 

Dies funktioniert, aber es ist für den Anrufer nicht schön. Statt

app.use(setupMiddleware()); 

ich tun, zu tun in der Lage:

setupMiddleware(functin (middleware) { 
    app.use(middleware); 
}); 

Jetzt dachte ich, ob es ein besserer Ansatz ist es, z.B. Lassen Sie die Middleware im Hintergrund initialisieren und verzögern Sie alle eingehenden Anfragen, bis die Middleware bereit ist.

Wie könnte ich das lösen? Irgendwelche Ideen oder Best Practices, die ich hier verwenden sollte?

Antwort

2

Ich löste es nun eine isInitialized Variable und Verzögerung der Middleware-Funktion selbst verwenden. Siehe das folgende Beispiel:

var connect = require('connect'); 

var setup = function() { 
    var isInitialized = false; 

    setTimeout(function() { 
    isInitialized = true; 
    }, 10000); 

    function run (req, res, next) { 
    res.write('Foo'); 
    res.end(); 
    } 

    function delay (req, res, next) { 
    if (isInitialized) { 
     return run(req, res, next); 
    } 

    setTimeout(function() { 
     delay(req, res, next); 
    }, 1000); 
    } 

    return function (req, res, next) { 
    if (req.url === '/foo') { 
     delay(req, res, next); 
     return; 
    } 
    next(); 
    } 
}; 

var app = connect(); 
app.use(setup()); 
app.use(function (req, res) { 
    res.write('Fertig!'); 
    res.end(); 
}); 

var http = require('http'); 

http.createServer(app).listen(5000); 

Bitte beachten Sie, dass dieser Code in irgendeiner Weise optimierte oder Refactoring nicht, es ist nur ein Beweis dafür, dass die Idee selbst funktioniert.

0

Warum Sie wie nicht tun, wie folgt

doSomeAsyncInitialization(function() { 
    //After doing all long running init process just configure your express as follows. 
    app.use(<middlewares>); 
    app.listen(<portnumder>); 

}); 
+1

Da die Initialisierung nur für eine Middleware ist, nicht für die gesamte App. Und dieses Muster funktioniert natürlich, aber es ist nicht "nett". Ich mag es nicht, dass alles um einen Schritt eingerückt ist (und das ist nicht nur ein Formatierungsproblem ;-)). –

+0

Ich akzeptiere es. Da Nodejs nicht blockierend ist, müssen Sie Code in einem lang andauernden Prozess-Callback oder in der Art, wie in Ihrer Frage gezeigt, erhalten. Ofcource, Sie können ein asynchrones Modul verwenden. Hier habe ich angenommen, dass Ihre Middleware für alle Anfragen obligatorisch ist, damit Sie in der app.use() -Funktion bleiben. Und mein Vorschlag ist, dass Sie die Middleware initialisieren, bevor Sie den Port abhören. Wenn Sie mehr als Formatierung erwarten, muss ich verstehen, was in der Funktion "doSomeAsyncInitialization" vor sich geht. –

+0

Nun, wie gesagt, eine Idee könnte sein, dass die Setup-Funktion sofort die Middleware zurückgibt, aber dass die Middleware eingehende Anfragen verzögert, bis sie vollständig initialisiert wurde. –