简体   繁体   English

为什么 JS 承诺不适用于猫鼬?

[英]Why is JS promise not working with mongoose?

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.从 ES5 开始我就没有接触过 JS,但我承诺的理解是我只是将回调移动到 .then() 中并称之为一天。 What am I missing here?我在这里缺少什么?

The Mongoose query update method will not execute if you don't pass it the callback function.如果不传递回调函数,Mongoose 查询update方法将不会执行。 This is stated in the docs on update :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 the exec() method.要在没有回调的情况下强制执行,我们必须首先调用update() ,然后使用exec()方法执行它。

So add .exec() to the chain, which will also return a full-fledged promise.所以将.exec()添加到链中,这也将返回一个成熟的承诺。

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. promise 的then方法有两个回调函数,第二个会在出错时调用,所以你必须拆分成功和失败代码。 And to be consistent you should completely switch over to using promises, and abandon the traditional callback pattern.为了保持一致,您应该完全切换到使用 Promise,并放弃传统的回调模式。 So the unfollow function should also itself return a 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()
    );

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.我只是将回调移动到.then()并称它为一天。 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.虽然节点回调有(err, result)参数,但 Promise 使用两种不同的回调——一种用于实现,一种用于拒绝——它们只传递一个参数。

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.为了利用promises真正力量,您需要返回链接它们。 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.通过不传递任何错误回调,拒绝将自动沿链冒泡,您无需关心明确转发所有错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM