我在用户控制器中有一个索引操作,其中我试图连续做两件事,并且在它们都有机会完成之前不执行所需的res.json()方法。
我有一个加入用户的友情加入模型。一列是frienderId,另一列是friendedId。在下面的索引函数中,期望的结果是我将得到一个单独的user对象,它是一个朋友。下面有promises的原因是因为用户可以在frienderId列中,也可以在friendedId列中,所以我必须解析req.user的朋友这两种可能的情况。
问题是返回的最后一件事,即res.json(result),总是返回正确的朋友,然而,它总是在所需对象之前或之后返回一个空的array []。我知道这个空数组来自两个未找到结果的promise场景之一。是否存在某种类型的方法,而不是像sayyy..reject那样的解析?其中,如果调用,整个promise不会被推送到promise数组中?然后我可以只测试(!friended) {reject}或(!friender) {reject}
我知道.each会枚举每个promise并给出每个promise的结果。然而,我不想要每个承诺的结果,我只想了解每个承诺运行的副作用。
谢谢!
index: function(req, res) {
var promiseArray = [];
promiseArray.push(new Promise(function(resolve) {
user.findById(req.user.id).then(function(user) {
user.getFrienders({
where: {
username: req.body.username
}
}).then(function(friender) {
resolve(friender[0])
})
})
}));
promiseArray.push(new Promise(function(resolve) {
user.findById(req.user.id).then(function(user) {
user.getFriendeds({
where: {
username: req.body.username
}
}).then(function(friended) {
resolve(friended[0])
})
})
}));
Sequelize.Promise.map(promiseArray, function(result) {
res.json(result);
});
}发布于 2016-09-20 07:32:27
首先,您对Promise的使用有点多余。因为findById()函数返回一个promise,所以您需要做的就是处理它。您不需要创建new Promise。你可以直接说promiseArray.push(user.findById ...)。您几乎可以正确地使用then了。传递给then的函数将在解析promise时调用,在本例中,是在findById函数完成并返回一个值之后调用的。then本身返回一个promise,该promise由其回调返回的值解析。因此,无论您希望在完成所有操作后返回promiseArray中的任何值,我假定为friended[0]或friender[0],您只需在最后一个then函数中返回该值。在第一个then函数中,您还应该使用return user.findFriends( ...
下一步需要做的是处理从findById函数返回的promise被拒绝的情况。您可以通过两种方式来完成此操作。首先,您可以将第二个回调传递给then,该回调将在promise被拒绝的情况下调用,其参数为reject的原因。不用将两个函数传递给then,您可以在then后面加上catch,这是我个人喜欢做的事情,并将您的拒绝回调传递给catch。catch还返回一个promise,该promise将使用其回调返回的值进行解析。你可以选择返回传入的原因,或者任何你想要的值。因此,在错误被拒绝的情况下,无论catch返回什么,最终都会出现在promises数组中。
阅读一下the documentation中的promises可能会对你有所帮助。诚然,当我刚开始的时候,我知道我在使用promises时遇到了一些困难,但在阅读了文档并制作了示例之后,您就会掌握它,并看到promises是多么有用。
如果是我,这就是我重构代码的方式
var frienderPromise = user.findById(req.user.id)
.then(function(user) {
return user.getFrienders({
where: { username: req.body.username }
});
})
.then(function (friender) {
return friender[0];
})
.catch(function (reason) {
return reason; // or whatever else you want to end up in the promisesArray on rejection
});
var friendedPromise = user.findById(req.user.id)
.then(function(user) {
return user.getFriendeds({
where: { username: req.body.username }
});
})
.then(function (friended) {
return friended[0];
})
.catch(function (reason) {
return reason;
});
promiseArray.push(frienderPromise);
promiseArray.push(friendedPromise);你可以保持其他一切不变。最后,您仍然可以像当前一样调用Sequalize。虽然它应该是return Sequalize...。如果不想保留糟糕的结果,还可以考虑使用Promise.filter而不是.map。所以你可以像这样做
return Sequelize.Promise.filter(promiseArray, function(result) {
if (/* make sure it's result you want */)
res.json(result);
});就我个人而言,我会更进一步,将所有的promise业务移到另一个与res无关的函数中,并以
return Sequelize.Promise.filter(promiseArray, function(result) {
return result === /* result you want */;
});然后,一旦进入index函数,您就可以调用
return friendsPromiseFunction().then(function (results) {
res.json(results);
})这会让事情变得更干净。
https://stackoverflow.com/questions/39583099
复制相似问题