我使用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()函数本身是一个承诺,这似乎可以捕获所有错误。
知识渊博的人是否能够确认我的过程是否良好可靠?谢谢!
答案 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)
})
}
您的原始函数调用代码无需更改即可使用。