2

我创建了一个处理动态帮助程序的外部文件,其中包括一堆我希望能够从我的所有视图中使用的函数。

在这些功能中,我正在运行一个查询并从数据库中获取标签,我想在我的 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(tags),它会打印出对象。但是,在下面的 dynamicHelper 函数中,它是未定义的。似乎 res.tags 由于某种原因没有传递给 dynamicHelper 。

动态助手.js:

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

配置.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
            });
        });
    });
};
4

3 回答 3

4

正如@Exploit在他的评论中所说,您的tags函数对 进行异步调用query.exec,这将在您的tags函数返回后完成。Express'helpers并且dynamicHelpers不能是异步的,因此您需要以某种方式对其进行重构。一种方法是将它放在req早期的中间件或路由中,然后有一个简单dynamicHelper的返回:

动态助手.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();
    });
});
于 2012-04-20T11:25:43.837 回答
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);
于 2012-04-20T00:28:25.770 回答
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());)
        // ...

    });
};
于 2012-04-23T07:33:01.413 回答