【问题标题】:Node.js and Express 3: Set app.locals that are loaded asynchrouslyNode.js 和 Express 3:设置异步加载的 app.locals
【发布时间】:2013-04-08 01:51:39
【问题描述】:

我使用的是 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;

}

感谢您的任何建议。

【问题讨论】:

    标签: node.js express ejs


    【解决方案1】:

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

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

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

    【讨论】:

    • 谢谢..我开始考虑与中间件相同的思路,我想我将能够像往常一样处理回调..在它返回之前不会调用 next() .
    猜你喜欢
    • 2016-01-02
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 2017-02-04
    • 1970-01-01
    • 2022-01-06
    • 2017-03-10
    相关资源
    最近更新 更多