var mongoose = require('mongoose');
import es6Promise from 'es6-promise';
mongoose.Promise = es6Promise.Promise;
const follow = (followerID, toFollowId, cb) => { //REVISE only update
User.update(
{ _id: toFollowId},
{$push: {usersFollowing: followerID}},
function(err){
if (err){
cb(true);
} else {
User.findByIdAndUpdate(
followerID,
{$push: {usersBeingFollowed: toFollowId}},
{safe: true, new: true},
function(err, model){
if (err){
cb(true);
} else {
cb(null, model);
}
}
)
}
}
)
}
const unfollow = (unfollowerId, toUnfollowId, cb) => { //REVISE only update
User.update(
{ _id: toUnfollowId},
{$pull: {usersFollowing: unfollowerId}}).then(
function(err){
if (err){
return cb(true);
} else {
User.findByIdAndUpdate(
unfollowerId,
{$pull: {usersBeingFollowed: toUnfollowId}},
{safe: true, new: true},
function(err, model){
if (err){
cb(true);
} else {
cb(null, model)
}
}
)
}
})
}
My follow function, which doesn't use a promise works fine. I tried editing my unfollow function to work as a promise, but it doesn't work. I haven't touched JS since ES5 but my promise understanding is that I just move the callback inside .then() and call it a day. What am I missing here?
The Mongoose query update
method will not execute if you don't pass it the callback function. This is stated in the docs on update
:
The operation is only executed when a callback is passed. To force execution without a callback, we must first call
update()
and then execute it by using theexec()
method.
So add .exec()
to the chain, which will also return a full-fledged promise.
The promise's then
method takes two callback functions, the second one will be called in case of error, so you have to split success and failure code. And to be consistent you should completely switch over to using promises, and abandon the traditional callback pattern. So the unfollow function should also itself return a promise:
const unfollow = (unfollowerId, toUnfollowId) =>
User.update(
{ _id: toUnfollowId },
{ $pull: { usersFollowing: unfollowerId } }
).exec()
.then( _ =>
User.findByIdAndUpdate(
unfollowerId,
{ $pull: { usersBeingFollowed: toUnfollowId } },
{ safe: true, new: true }
).exec()
);
You would call that as:
unfollow(unfollowerId, toUnfollowId).then( model => {
// success
}, err => {
// failure
});
I just move the callback inside
.then()
and call it a day. What am I missing here?
That the callback convention changes as well. While node callbacks have (err, result)
arguments, promises use two distinct callbacks - one for fulfillment and one for rejection - that get passed only one argument.
While you could in theory do
User.update(…).then(function(_) {
User.findByIdAndUpdate(…);
}, function(err){
cb(true);
});
that would be an awful practise. To leverage the true power of promises , you need to return and chain them. In your case, that would be
function unfollow(unfollowerId, toUnfollowId) {
// ^ no more callback
return User.update(
// ^^^^^^ return the result of the `then` call
{ _id: toUnfollowId},
{$pull: {usersFollowing: unfollowerId}}
).then(_ => {
return User.findByIdAndUpdate(
// ^^^^^^ just return the promise
unfollowerId,
{$pull: {usersBeingFollowed: toUnfollowId}},
{safe: true, new: true}
// that you get when no longer passing a callback
);
});
}
By not passing any error callbacks, rejections will automatically bubble down the chain, and you don't need to care about forwarding all errors explicitly.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.