【问题标题】:Syntax for chaining mongoose promises链接猫鼬承诺的语法
【发布时间】:2018-09-01 07:36:51
【问题描述】:

我对使用 Promises 和 MongoDB / Mongoose 比较陌生,我正在尝试将多个数据库查询的流程链接成一个高效可靠的函数。

我想知道我的最终功能是否是实现我想要的良好且可靠的方法,或者是否存在任何问题或可以进行的任何改进。

流程如下:

1) 检查用户是否已经存在

usersSchema.findOne({
    email: email
}).then(res => {
    if(res==null){
        // user does not exist
    }
}).catch(err => {});

2) 将新用户添加到数据库中

var new_user = new usersSchema({ email: email });
new_user.save().then(res => {
    // new user id is res._id
}).catch(err => {});

3) 为用户分配一个免费的促销代码

codeSchema.findOneAndUpdate({
    used: false,
    user_id: true
},{
    used: true,
    user_id: mongoose.Types.ObjectId(res._id)
}).then(res => {
    // user's code is res.code
}).catch(err => {});

显然,每个查询都需要按顺序执行,因此在对如何执行此操作进行了大量研究和实验后,我将查询组合成以下函数,目前看来工作正常:

function signup(email){
    // check email isn't already signed up
    return usersSchema.findOne({
        email: email
    }).then(res => {
        if(res==null){
            // add to schema
            var new_user = new usersSchema({ email: email });
            // insert new user
            return new_user.save().then(res => {
                var result = parse_result(res);
                // assign a code
                return codesSchema.findOneAndUpdate({
                    used: false,
                    user_id: true
                },{
                    used: true,
                    user_id: mongoose.Types.ObjectId(result._id),
                });
            });
        }else{
            return 'The user already exists';
        }
    });
}

signup('test@test.com').then(res => {
    console.log('success, your code is '+res.code);
}).catch(err => {
    console.log(err);
});

我仍在努力弄清楚它是如何工作以及为什么工作的 - 函数正在返回一个承诺,每个嵌套的承诺都在返回一个承诺。

我主要担心的是存在大量嵌套(是否有办法通过链接 .then() 回调而不是嵌套所有内容来做到这一点?)并且嵌套的 Promise 似乎没有错误捕获,尽管由于 signup() 函数本身是一个承诺,这似乎捕获了所有错误。

是否有任何了解该主题的人能够确认我的流程看起来是否良好和可靠?谢谢!

【问题讨论】:

    标签: javascript node.js mongodb mongoose promise


    【解决方案1】:

    为了避免缩进,如果你从传递给 Promise 的 .then() 方法的函数返回一个值,你可以将多个 .then() 链接成一个整洁的管道。请注意,您也可以返回一个具有待处理状态的 Promise,然后在它解决后执行下一个函数。

    function signup (email) {
      return usersSchema.findOne({
        email: email
      }).then(res => {
        if (res) throw 'The user already exists'
        var new_user = new usersSchema({ email: email })
        return new_user.save()
      }).then(res => {
        var result = parse_result(res)
        return codesSchema.findOneAndUpdate({
          used: false,
          user_id: true
        },{
          used: true,
          user_id: mongoose.Types.ObjectId(result._id)
        })
      })
    }
    

    更好的是,如果你有可能使用async/await(Node v7.6 或更高版本),你的代码看起来就像普通的阻塞代码:

    async function signup (email) {
      let user = await usersSchema.findOne({ email: email })
      if (user) throw 'The user already exists'
      let new_user = await new usersSchema({ email: email }).save()
      let result = parse_result(new_user)
      return codesSchema.findOneAndUpdate({
        used: false,
        user_id: true
      },{
        used: true,
        user_id: mongoose.Types.ObjectId(result._id)
      })
    }
    

    您的原始函数调用代码无需更改即可在两者上运行。

    【讨论】:

    • 谢谢,这些都是很好的例子!我以前玩过 async/await,但这有助于澄清它的用途!
    【解决方案2】:

    你的代码可以这样改进

    function signup(email){
        // check email isn't already signed up
        return usersSchema.findOne({
            email: email
        }).then(res => {
            if(res==null){            // add to schema
                var new_user = new usersSchema({ email: email });
                // insert new user
                return new_user.save()
            }else{
                return Promise.reject(new Error('The user already exists'));
            }
        })
        .then(res => {
            var result = parse_result(res);
            // assign a code
            return codesSchema.findOneAndUpdate({used: false,user_id: true},{used: true,user_id: mongoose.Types.ObjectId(result._id),});
        });
    
    }
    
    signup('test@test.com').then(res => {
        console.log('success, your code is '+res.code);
    }).catch(err => {
        console.log(err);
    });
    

    【讨论】:

      猜你喜欢
      • 2019-06-04
      • 2018-02-15
      • 2016-11-01
      • 2015-05-12
      • 1970-01-01
      • 1970-01-01
      • 2012-12-14
      • 2017-06-15
      • 2017-08-18
      相关资源
      最近更新 更多