Express.js的外部configuration

我使用Express.js构build了一个小型Node应用程序,为了尽可能保持我的server.js文件干净,我想在外部文件中构build我的configuration。 以下是服务器的外观:

 // server.js var express = require( 'express' ); var app = express(); app.enable( 'trust proxy' ); // Set application config params require( './config.js' )( app, express ); // Load routes and start listening... require( './routes' )( app ); app.listen( app.get( 'port' ) ); 

我的config.js文件设置了一些默认值,然后在NODE_ENV特定的configuration函数中更新或覆盖configuration。 一切都会很好,除了那个讨厌的时机。

我的路线需要访问一些configuration值。 有没有办法确保我的路线加载和我的服务器启动只有configuration完全加载后才开始侦听? 有没有更好的办法?

我得到了事件循环,但我是新的节点/快递品牌,所以我打开几乎任何东西。 我是这样做的,因为我一直在根据经验与我在各种文章或文档资料中阅读的内容进行协调。 我不认为我在这里太离谱,但也许这是过于乐观。

UPDATE

我的config.js

 module.exports = function( app, express ) { var config = this; app.configure( function() { app.set( 'port', 3000 ); app.set( 'datasources', { 'api' : {...}, 'mysql' : {...} }); app.use( express.logger() ); app.use( express.bodyParser() ); app.use( express.cookieParser() ); app.use( express.methodOverride() ); app.use( app.router ); }); // dev-specific config app.configure( 'development', function() { console.log( 'Loading development configuration' ); app.use( express.errorHandler({ dumpExceptions: true, showStack: true }) ); // update the mysql config with a connection object var datasources = app.get( 'datasources' ); var mysqlConnection = require( 'mysql' ).createConnection({...}); datasources.mysql.connection = mysqlConnection; app.set( 'datasources', datasources ); }); // stg-specific config app.configure( 'staging', function() { console.log( 'Loading staging configuration' ); app.use( express.errorHandler() ); // update the mysql config with a connection object var datasources = app.get( 'datasources' ); var mysqlConnection = require( 'mysql' ).createConnection({...}); datasources.mysql.connection = mysqlConnection; app.set( 'datasources', datasources ); }); // prd-specific config app.configure( 'production', function() { console.log( 'Loading production configuration' ); app.use( express.errorHandler() ); }); console.log( app.get( 'datasources' ) ); console.log( 'Configuration loaded' ); return config; }; 

如果你的configuration里面的代码都是同步的,这应该工作:

 // server.js var express = require( 'express' ); var app = express(); var config = require( './config.js' ); // load config app.enable( 'trust proxy' ); // ----------------------------------------------- // If the code inside your config is all synchronous this call // will block, which is what you want. config(app, express ); // Load routes and start listening... require( './routes' )( app ); app.listen( app.get( 'port' ) ); 

将callback分配给你的config.js模块,让它看起来像

 require( './config.js' )( app, express, finish ); var finish = function(){ // Load routes and start listening... require( './routes' )( app ); app.listen( app.get( 'port' ) ); } 

在你的configuration方法中,使用像async这样的模块,并使所有加载同步到最后并callback函数。 例:

 **config.js** module.exports = function(app,express,finish){ function loadConfig1(cb){ fs.readFile("....", function(){ // Or someother else async function ... if succesfull, cb(null); ... if fail, cb("error!!!!"); }); } .... function complete(err, results){ if (!err){ finish(); // you guarantee that all the functions are completed succesfully } } } 

我目前正在对Express进行扩展,允许纯JSON外部路由configuration。 我计划在不久的将来开源这个项目。 如果有人有兴趣,我很乐意通过Github和NPM分享这个项目的早期预览

 module.exports = { /** * settings */ config:{ "controller_directory" : "routes" }, /** * defaults to ./routes directory */ filters: { secure: "secure.securityListener", global:"secure.globalListener" }, /** * defaults to ./routes directory * order matters for filters * filters should always contain a path which calls next(); * router should be the final destination to a request * * possible verbs are [use, all, get, post, delete ...] * "use" is the default, "mount" path is stripped and is not visible to the middleware function. * other verbs will not strip out the "mount" path */ routes: { global: {"filters": ["global"]}, index:{path:"/", "controller": "index"}, users:{path:"/users", "controller": "users", "filters": ["secure"]}, prices:{path:"/prices", "controller": "prices"}, software:{path:"/software", "controller": "software"}, auth:{path:"/auth", "controller": "secure.onAuthentication", "verb": "get"} } };