Node.js 返回的对象未使用dynamicHelpers定义

Node.js 返回的对象未使用dynamicHelpers定义,node.js,express,mongoose,pug,Node.js,Express,Mongoose,Pug,我已经创建了一个处理动态助手的外部文件,其中包括一系列我希望能够从所有视图中使用的函数 在其中一个函数中,我正在运行一个查询并从数据库中获取标记,我想在layout.jade文件中使用它(所有其他视图都在使用它)。在控制台中,一切似乎都正常。查询返回tags对象,但由于某种奇怪的原因,我无法将该对象返回到视图,这给了我一条错误消息,告诉我“tags”未定义 这是我的文件dynamicHelpers.js中的代码: exports.tags = function(req, res){ va

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

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

这是我的文件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;
    });
}
exports.tags = function(req, res) {
    console.log(req.tags); <--- undefined
    return req.tags;
};
exports.tags = function(req, res) {
    return req.tags;
};
在layout.jade中,我以这种方式获取对象(显示未定义):

我实际上想做的是循环遍历所有带有“each”的标记。因此,后续问题是,这是否允许并且可能(如果“tags”未定义)

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

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;
    });
}
exports.tags = function(req, res) {
    console.log(req.tags); <--- undefined
    return req.tags;
};
exports.tags = function(req, res) {
    return req.tags;
};
exports.tags=函数(请求、恢复){

console.log(req.tags);它有点脏,但您可以这样做以等待设置标记。不过,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);
正如@Exploit所说,您的
标记
函数对
查询.exec进行异步调用,该调用将在
标记
函数返回后完成。Express'
助手
dynamicchelpers
不能是异步的,因此您需要以某种方式对其进行重构。一种方法是在较早的时候将其置于
req
上中间件或路由,然后有一个简单的
dynamicHelper
,它返回:

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;
    });
}
exports.tags = function(req, res) {
    console.log(req.tags); <--- undefined
    return req.tags;
};
exports.tags = function(req, res) {
    return req.tags;
};
中间件(您可能不希望对所有路由执行此操作,您可以查看,例如或):


您需要在其他路由之前定义中间件

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());)
        // ...

    });
};
module.exports=函数(应用程序、express、下一个){
app.configure(函数(){
应用程序使用(功能(请求、恢复、下一步){
var-environment=require(“./environment”);
var服务=需要(“./服务”);
service.init(环境);
var model=service.useModel('tag');
var query=model.Tag.find({});
exec(函数(错误、标记){
如果(错误){
返回下一个(错误);
}
req.tags=标签;
next();

log(req.tags);感谢您的回答。问题是dynamicHelper工作得很好,所以它不是“必需的”“问题。只是对象本身似乎没有返回。:/这可能是因为query.exec是异步的,并且函数在查询完成之前返回。问题是,使用console.log(标记)可以很好地打印对象。”,在返回之前。@JasonCraig它将显示在日志语句中,但那是在
标记
函数返回之后,因为
query.exec
是异步的。谢谢!我已经尝试了上面的代码,但是我在req.tags上没有定义?而且您在到达路由之前使用中间件?是的,我想至少是这样。请查看我的现在更新了一个问题,解释了它现在是如何实现的。也许我做错了什么?试着在您测试的路径中执行
控制台.log
,看看哪个log语句最先出现。可能是这样的情况,它在响应后获取标记。@JasonCraig——如果确实要解决这个问题:如果您有一行
app.use(app.router)
,确保这是在我的示例中的中间件之后。如果没有,请确保在执行任何
应用程序之前调用
配置
模块。