返回的对象未定义,使用 dynamicHelpers

Posted

技术标签:

【中文标题】返回的对象未定义,使用 dynamicHelpers【英文标题】:Returned object is undefined, using dynamicHelpers 【发布时间】:2012-05-01 11:07:15 【问题描述】:

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

在其中一个函数中,我正在运行查询并从数据库中获取标签,我想在我的 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。

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
            );
        );
    );
;

【问题讨论】:

【参考方案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());)
        // ...

    );
;

【讨论】:

【参考方案2】:

这有点脏,但您可以这样做以等待设置标签。不过,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);

【讨论】:

感谢您的回答。问题是 dynamicHelper 工作正常,所以这不是“需要”问题。只是对象本身好像没有返回。:/ 这可能是因为 query.exec 是异步的,并且函数在查询完成之前返回。 问题是对象在返回之前用 console.log(tags) 打印出来了。 @JasonCraig 它将显示在您的日志语句中,但那是在您的 tags 函数返回之后,因为 query.exec 是异步的。【参考方案3】:

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

dynamicHelpers.js:

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

中间件(您可能不想对所有路由都这样做,您可以查看例如 Route specific middleware 或 Route 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();
    );
);

【讨论】:

谢谢!我已经尝试了上面的代码,但我在 req.tags 上未定义? 你在到达的路由之前使用中间件? 是的,至少我是这么认为的。请查看我现在更新的问题,该问题解释了它现在是如何实施的。也许我做错了什么? 尝试在您正在测试的路由中执行console.log,并查看哪个日志语句先出现。可能是响应后获取标签的情况。 @JasonCraig -- 如果你确实想解决这个问题:如果你有一行app.use(app.router),请确保它出现在我的示例中的中间件之后。如果不这样做,请确保在调用configuration 模块之前 调用app.getapp.post 等等。

以上是关于返回的对象未定义,使用 dynamicHelpers的主要内容,如果未能解决你的问题,请参考以下文章

即使值存在,为啥对象键返回未定义

API 返回数据,但在未定义的对象中。这是怎么回事?

订阅可观察对象返回未定义

返回对象中的“未定义”字段

当我使用点表示法时,字段返回未定义

Javascript对象在函数内返回未定义