链接mongoose promises的语法

时间:2018-03-22 18:21:36

标签: javascript node.js mongodb mongoose promise

我使用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);
});

我仍然试图了解其工作原理和原因 - 函数返回一个promise,每个嵌套的promise都会返回一个promise。

我主要担心的是有很多嵌套正在进行(有没有办法通过链接.then()回调而不是嵌套所有东西来做到这一点?)并且嵌套的promises似乎没有错误捕获,虽然signup()函数本身是一个承诺,这似乎可以捕获所有错误。

知识渊博的人是否能够确认我的过程是否良好可靠?谢谢!

2 个答案:

答案 0 :(得分:1)

您可以通过这种方式改进代码

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

答案 1 :(得分: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)
  })
}

您的原始函数调用代码无需更改即可使用。