蓝鸟承诺在快递/猫鼬中过早返回

时间:2016-02-27 17:14:15

标签: node.js express mongoose promise bluebird

我是承诺的新手,并想知道为什么以下不起作用。我假设是因为我需要设置我的自定义方法以使用Promise的特定方式。

我使用蓝鸟作为我的Promise库。我想获得一个"讨论列表"对象给予用户""用户名通过在这些相应模型上使用mongoose静态和方法(即讨论和用户模型)。

下面是我在Express中的请求处理程序。只是尝试获取JSON并将其作为响应发送到现在:

/* /routes/users.js */

var Promise = require('bluebird');
var User = require('../models/').User

/* ... express inclusions, other routes ... */

/* Get list of discussions for user */
router.get('/:username/discussions', function(req, res) {
    User.findOne({username: req.params.username}).then(function(user) {
        if (user) {
            return user.getDiscussions();
        } else {
            res.send('no user found');
        }
    }).then(function(discussions) {
        res.send(discussions);
    }).catch(function(error) {
        console.log('ERROR: ' + error);
        res.send('ERROR: ' + error);
    });
});

以下是user.getDiscussions():

/* /models/user.js */

var Promise = require('bluebird');
var mongoose = Promise.promisifyAll(require('mongoose'));
var Discussion = require('./discussion').Discussion;
var Schema = mongoose.Schema;

/* ... UserSchema defined here ... */

UserSchema.methods.getDiscussions = Promise.method(function() {
    var self = this;
    self.model('User').findById(self.id).then(function(user) {
        if (!user) {
            Promise.reject('User \'' + self.id + '\' does not exist.');
        } else {
            return Discussion.getDiscussionsForUser(self.username);
        }
    });
});

最后,Discussion.getDiscussionsForUser:

/* /models/discussion.js */

var Promise = require('bluebird');
var mongoose = Promise.promisifyAll(require('mongoose'));
var Schema = mongoose.Schema;

/* ... DiscussionSchema defined here ... */

DiscussionSchema.statics.getDiscussionsForUser = Promise.method(function(username) {
    var self = this;
    self.model('User').findOne({username: username}, 'discussions').then(function(user) {
        if (!user) {
            return Promise.reject('User with username \'' + username + '\' does not exist.');
        } else {
            var discussions = [];
            return self.model('Discussion').find({
                '_id': { $in : user.discussions }
            });
        }
    });
});

似乎路由中的请求提前完成并在响应中发送undefined。知道为什么在讨论模型中从Mongoose那里获得的讨论没有冒充到路线上吗?

1 个答案:

答案 0 :(得分:2)

getDiscussions()getDiscussionsForUser()未正确返回承诺。按如下方式更改它们:

UserSchema.methods.getDiscussions = Promise.method(function() {
    var self = this;
    // *** added a return to this next line
    return self.model('User').findById(self.id).then(function(user) {
        if (!user) {
            // *** added a return to this next line
            return Promise.reject('User \'' + self.id + '\' does not exist.');
        } else {
            return Discussion.getDiscussionsForUser(self.username);
        }
    });
});

getDiscussionsForUser()相同,应该是这样的:

DiscussionSchema.statics.getDiscussionsForUser = Promise.method(function(username) {
    var self = this;
    // *** added a return to the next line
    return self.model('User').findOne({username: username}, 'discussions').then(function(user) {
        if (!user) {
            return Promise.reject('User with username \'' + username + '\' does not exist.');
        } else {
            var discussions = [];
            return self.model('Discussion').find({
                '_id': { $in : user.discussions }
            });
        }
    });
});

为了使调用者能够使用promises协调函数内异步操作的完成,通过该函数的所有代码路径必须始终从该函数返回一个promise。一旦进入.then()处理程序,如果有进一步嵌套的异步操作,则必须返回一个promise,或者如果希望该值成为您所在的promise的值,则可以返回一个值。