Node.js和Express 3:设置异步加载的app.locals

时间:2013-04-07 14:18:41

标签: node.js express ejs

我正在使用Node.js和Express 3.0,我很清楚app.locals和res.locals之间的区别......

我想在我的任何EJS模板中设置一些全局引用的app.locals变量('newest'和'popular')。这些变量的数据来自数据库(CouchDB / Cradle),也可以通过我的app.routes(即:/ myappdata)访问,它只是以res.json的形式从数据库中公开我的应用程序数据。

那么将一次加载到我的app.locals中的最佳方法是什么?我应该在路由器之前使用app.use()创建中间件功能吗?如何确保不会在每个请求上调用数据库,并且仅在我的应用程序启动时?我应该如何在app.use()中进行异步回调?

我也尝试过直接设置app.locals(),但似乎在某些时候,“最新”和“流行”变量对我的模板“未定义”。 (也许某事正在踩到app.locals?)

这是我在启动时返回给server.js的'app.js':

var express = require('express'),
    engine = require('ejs-locals'),
    conf = require('./conf'),
    cradle = require('cradle').(conf.databaseConn),
    app = express();

exports.init = function(port) {

    app.locals({
        _layoutFile:'layout.ejs',
        newest:{}, // like to set this from db once
        popular:{} // like to set this from db once
    });

    app.configure(function(){
        app.set('views', __dirname + '/views');
        app.set('view engine', 'ejs');

        app.use(express.compress());

        app.use(express.static(__dirname + '/static'));

        app.use(express.bodyParser());
        app.use(express.cookieParser());
        app.use(express.cookieSession({cookie:{path:'/',httpOnly:true,maxAge:null},secret:'blh'}));

        app.use(function(req, res, next){
            res.locals.path = req.path;
            res.locals.user = req.session.user;
            next();
        });

        app.use(app.router);
    });

    app.engine('ejs', engine);

    app.configure('development', function(){
        app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
    });

    app.configure('production', function(){
        app.use(express.errorHandler()); 
    })

    app.use(function(err, req, res, next){
        res.render('500.ejs', { locals: { error: err, path:"" },status: 500 }); 
    });

    var server = app.listen(port);
    console.log("Listening on port %d in %s mode", server.address().port, app.settings.env);
    return app;

}

感谢您的任何建议。

1 个答案:

答案 0 :(得分:6)

您可以创建一个中间件来检查是否定义了app.locals.newest(/ .popular);如果是这样,请立即致电next();如果没有,执行数据库查询,将结果存储在app.locals中,并调用next()(这就是创建异步中间件的方式)。如果以这种方式实现,则将在第一个(也是第一个)请求期间执行查询。

另一种方法是在调用app.listen()之前在启动时执行查询。这样,您确定在服务器开始侦听请求时加载变量。

要协调多个异步数据库查询,您可以使用asyncqueue等模块。