蓝鸟答应在快递/mongoose中过早返回

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

我使用蓝鸟作为我的诺言库。 我试图通过在这些模型(即讨论和用户模型)上使用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 } }); } }); }); 

似乎路由中的请求提前完成,并在响应中发送未定义的请求。 任何想法,为什么在讨论模式中从mongoose中获得的讨论不是冒险的路线?

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

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