使用dynamicHelpers未定义返回的对象

时间:2012-04-19 20:46:13

标签: node.js express mongoose pug

我创建了一个处理动态助手的外部文件,其中包含一系列我希望能够在所有视图中使用的函数。

在函数中,我正在运行查询并从数据库中获取标记,我想在layout.jade文件中使用它(所有其他视图都在使用)。在控制台中,一切似乎都可以。查询返回标签对象,但由于一些奇怪的原因我无法将对象返回到视图,这给了我一条错误消息,告诉我“标签”未定义“。

这是我的文件dynamicHelpers.js中的代码:

exports.tags = function(req, res){
    var environment = require('../environment');
    var service = require('../service');
        service.init(environment);

    var model = service.useModel('tag');

    var query = model.Tag.find({});
    query.exec(function (err, tags) {
        if (err) {
            console.log(err);
            // do something
        }
        console.log(tags);
        return tags;
    });
}
在layout.jade中

我以这种方式获取对象(这显示未定义):

p
    #{tags}

我真正想做的是用'each'遍历所有标签。因此,如果允许并且可能(如果'标签'未定义),后续问题将是什么?

ul.tags
    each tag in #{tags}
        a(href='/tag/' + tag._id.toHexString())
            li.tag= tag.name

更新 我已经尝试了@Linus G Thiel的解决方案(见下文),但无法使其工作(res.tags未定义)。使用中间件中的console.log(标签),它会打印出对象。但是,在下面的dynamicHelper函数中,它是未定义的。似乎res.tags没有因某种原因传递给dynamicHelper。

dynamicHelpers.js:

exports.tags = function(req, res) {
    console.log(req.tags); <--- undefined
    return req.tags;
};

configuration.js:

module.exports = function(app, express, next){
    app.configure(function() {
        // lots of more app.use functions (eg. express.cookieParser());)
        // ...

        app.use(function(req, res, next) {
            var environment = require('./environment');
            var service = require('./service');
                service.init(environment);

            var model = service.useModel('tag');

            var query = model.Tag.find({});
            query.exec(function (err, tags) {
                if (err) {
                    return next(err);
                }
                req.tags = tags;
                next();
            console.log(req.tags); <--- works fine
            });
        });
    });
};

3 个答案:

答案 0 :(得分:4)

正如@Exploit所说in his comment,您的tags函数会对query.exec进行异步调用,这将在您的tags函数返回后完成。 Express'helpersdynamicHelpers不能异步,所以你需要以某种方式重构它。一种方法是将它放在req的早期中间件或路由中,然后使用一个简单的dynamicHelper返回:

dynamicHelpers.js:

exports.tags = function(req, res) {
    return req.tags;
};

中间件(您可能不希望对所有路由执行此操作,您可以查看例如Route specific middlewareRoute param pre-conditions):

app.use(function(req, res, next) {
    var environment = require('../environment');
    var service = require('../service');
        service.init(environment);

    var model = service.useModel('tag');

    var query = model.Tag.find({});
    query.exec(function (err, tags) {
        if (err) {
            return next(err);
        }
        req.tags = tags;
        next();
    });
});

答案 1 :(得分:1)

它有点脏,但你可以这样做等待标签设置。 Linus G Thiel提供的解决方案更好,因为这会阻止您的应用程序。

tags: function(req, res) {
    var environment = require('../environment');
    var service = require('../service');
    service.init(environment);

    var model = service.useModel('tag');
    var query = model.Tag.find({});
    var _tags = false;

    query.exec(function (err, tags) {
        if (err) {
            console.log(err);
            // do something
        }

        console.log(tags);
        _tags = tags;
    });

    while(_tags == false);

    return _tags;
}

你试过这样的吗?

exports = function(app) {
    app.dynamicHelpers({
        tags: function(req, res) {
            var environment = require('../environment');
            var service = require('../service');
            service.init(environment);

            var model = service.useModel('tag');

            var query = model.Tag.find({});
            query.exec(function (err, tags) {
            if (err) {
                console.log(err);
                // do something
            }
            console.log(tags);
            return tags;
            });
        }
    });
}

require("helpers")(app);

答案 2 :(得分:1)

您需要在之前定义中间件

module.exports = function(app, express, next){
    app.configure(function() {

        app.use(function(req, res, next) {
            var environment = require('./environment');
            var service = require('./service');
                service.init(environment);

            var model = service.useModel('tag');

            var query = model.Tag.find({});
            query.exec(function (err, tags) {
                if (err) {
                    return next(err);
                }
                req.tags = tags;
                next();
            console.log(req.tags); <--- works fine
            });
        });

        // lots of more app.use functions (eg. express.cookieParser());)
        // ...

    });
};