2

我正在使用 Express.js 构建一个小型 Node 应用程序,并且为了使我的server.js文件尽可能干净,我想在外部文件中构建我的配置。这是服务器的外观:

// 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特定配置函数中的配置。除了那个讨厌的时机,一切都会好起来的。

我的路线需要访问一些配置值。有没有办法确保我的路由已加载并且我的服务器仅配置完全加载后才开始侦听?有没有更好的办法?

我得到了事件循环,但我是 node/express 的新手,所以我对几乎任何事情都持开放态度。在我进行的过程中,我根据我在各种文章或文档资源中所读到的内容,将我知道我想做的事情拼凑在一起,从而弥补了这一点。我认为我在这里并不过分,但也许这过于乐观了。

更新

我的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;
};
4

3 回答 3

2

将回调分配给您的 config.js 模块,让它看起来像

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

在您的配置方法中,使用async之类的模块,并在最后使所有加载同步并回调函数。例子:

**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
         }
    }
}
于 2013-01-24T18:31:34.287 回答
2

如果您的配置中的代码都是同步的,这应该可以工作:

// 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' ) );
于 2013-01-24T18:53:00.867 回答
-1

我目前正在开发 Express 的扩展,它允许纯 json 外部路由配置。我计划在不久的将来开源这个项目。如果有人感兴趣,我很乐意通过 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"}
  }

};
于 2014-06-24T17:13:06.653 回答