【问题标题】:Why is JS promise not working with mongoose?为什么 JS 承诺不与猫鼬一起工作?
【发布时间】:2017-02-08 06:00:16
【问题描述】:
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() 中并收工。我在这里错过了什么?

【问题讨论】:

  • “它不起作用”
  • User.update 是否返回一个 Promise?承诺解决了吗?

标签: javascript promise es6-promise


【解决方案1】:

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

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

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

promise 的then 方法有两个回调函数,第二个回调函数会在出错的情况下被调用,所以你必须拆分成功和失败代码。为了保持一致,您应该完全切换到使用 Promise,并放弃传统的回调模式。所以 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
});

【讨论】:

【解决方案2】:

我只是将回调移动到.then() 中并收工。我在这里错过了什么?

回调约定也发生了变化。虽然节点回调有 (err, result) 参数,但 Promise 使用两个不同的回调——一个用于实现,一个用于拒绝——它们只传递一个参数。

理论上你可以做到

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

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

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

通过不传递任何错误回调,拒绝将自动沿链冒泡,您无需关心显式转发所有错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 2014-02-15
    • 2018-02-15
    • 1970-01-01
    • 1970-01-01
    • 2019-02-13
    • 2012-12-14
    相关资源
    最近更新 更多