为什么JS承诺不与mongoose合作?

时间:2017-02-07 12:07:22

标签: javascript promise es6-promise

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

我的跟随功能,没有使用承诺可以正常工作。我尝试编辑我的取消关注功能以作为承诺,但它不起作用。自ES5以来我没有触及过JS,但我的承诺是我只是将回调移到.then()中并将其称为一天。我在这里缺少什么?

2 个答案:

答案 0 :(得分:0)

如果您没有将回调函数传递给它,则不会执行Mongoose查询update方法。这在docs on update

中说明
  

仅在传递回调时执行操作。要在没有回调的情况下强制执行,我们必须先调用update(),然后使用exec()方法执行它。

所以将.exec()添加到链中,这也将返回一个完整的承诺。

promise then方法需要两个回调函数,第二个函数会在出错时被调用,因此您必须分割成功和失败代码。为了保持一致,你应该完全切换到使用promises,并放弃传统的回调模式。所以 unfollow 函数本身也应该返回一个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()
    );

您可以将其称为:

unfollow(unfollowerId, toUnfollowId).then( model => {
    // success
}, err => {
    // failure
});

答案 1 :(得分:0)

  

我只是在.then()内移动回调并将其称为一天。我在这里缺少什么?

回调约定也会改变。虽然节点回调有(err, result)个参数,但promises使用两个不同的回调 - 一个用于履行,一个用于拒绝 - 只传递一个参数。

虽然你理论上可以做到

User.update(…).then(function(_) {
    User.findByIdAndUpdate(…);
}, function(err){
    cb(true);
});

这将是一个糟糕的做法。要利用true power of promises,您需要返回。在你的情况下,那将是

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

如果没有传递任何错误回调,拒绝将自动在链中冒泡,您无需关心明确转发所有错误。