3

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

我想设置一些我想在我的任何 EJS 模板中全局引用的 app.locals 变量(“最新”和“流行”)。这些变量的数据来自数据库(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;

}

感谢您的任何建议。

4

1 回答 1

6

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

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

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

于 2013-04-07T17:51:39.953 回答