首先,我不会否认我对承诺很新,并试图在我的新Node.js应用程序中更好地管理承诺。我根据朋友和社区的意见使用蓝鸟。这是一个场景:
该应用有一个注册流程,这是一个典型的用例,必须在以下事件中注册才能注册新用户:
我确实有3个独立的功能来解决上述每个步骤。
现在这里是我使用promises flow得出的结果......但不知何故我不相信下面的代码:
user.isExistingUser(email)
.then((successData) => {
if(successData && successData.length === 0) {
user.signUp(signUpInfo)
.then((successData) => {
emailService.sendVerificationEmail(recipientInfo)
.then((successData) => {
res.json(responseUtility.getApiResponse(successData));
})
.catch((errorObj) => {
res.json(responseUtility.getApiResponse(null, null, errorObj));
});
})
.catch((errorObj) => {
res.json(responseUtility.getApiResponse(null, null, errorObj));
});
} else {
res.json(responseUtility.getApiResponse(null, [{
param: 'email',
msg: 'An account already exists with this email'
}], null));
}
})
.catch((errorObj) => {
res.json(responseUtility.getApiResponse(null, null, errorObj));
});
正如您可能会看到代码似乎有点太长而且跟踪可能会变得有点棘手。一些蓝鸟专家可以帮助提供更好或更易读的代码吗?
答案 0 :(得分:2)
你应该更好地利用链接。始终return
承诺从您的函数执行异步操作。
user.isExistingUser(email).then(successData => {
if (successData && successData.length === 0) {
return user.signUp(signUpInfo).then(() => {
// ^^^^^^
return emailService.sendVerificationEmail(recipientInfo);
// ^^^^^^
}).then(successData => {
res.json(responseUtility.getApiResponse(successData));
});
} else {
res.json(responseUtility.getApiResponse(null, [{
param: 'email',
msg: 'An account already exists with this email'
}], null));
}
}).catch(errorObj => {
res.json(responseUtility.getApiResponse(null, null, errorObj));
});
答案 1 :(得分:1)
Unserstand您的代码有什么问题
基本上,您的代码是嵌套回调。典型的嵌套回调如下:
funcation(args..,
function(args...,
function(args){...}
){...}
){...}
你的喜欢:
function(args).then(()=> {
function(args).then(() => {
function(args){...}
})
})
差别不大,不是吗?
这是使用Promise的正确方法。
解决问题的关键是将承诺链接起来。这实际上是承诺的全部要点。
基本上,您希望then
回调返回一个承诺。这样,您可以链接您的承诺,以避免嵌套的回调样式的代码。
每个.then
方法总是返回一个承诺本身。
promiseB = promiseA.then(()=> {
// callback
return promiseC
});
如果callback
返回上述承诺,您可以有效地考虑promiseB = promiseC
。现在,如果我们有
promiseC = promiseA.then(()=> {
// callback
return promiseB
});
promiseE = promiseC.then(()=> {
// callback
return promiseD
});
您可以将链接在一起。然后上面可以缩短为:
promiseA.then(()=> {
// callback
return promiseB
}).then(()=> {
// callback
return promiseD
});
直接回答您的问题。
let userPromise = user.isExistingUser(email);
// handle new user
userPromise
.then((userData) => {
assert userData.length === 0;
// sign up
// Assuming user.signUp is a Promise with recipientInfo as its resolved value
return user.signUp(userData.signUpInfo);
})
.then((recipientInfo)=> {
// send verification email
// Assuming user.sentVerificationEmail is a Promise with emailSuccessData as its resolved value
return user.sentVerificationEmail(recipientInfo)
})
.then((emailSuccessData)=> {
res.json(responseUtility.getApiResponse(emailSuccessData));
})
// if any of the previous Promise is rejected,
// the follow .then will be effectively bypassed and fall though to this catch
.catch((err)=> {
res.json(responseUtility.getApiResponse(null, null, err));
})
// handle existing user
userPromise.then((successData) => {
assert successData.length > 0
const json = [{
param: 'email',
msg: 'An account already exists with this email'
}]
res.json(responseUtility.getApiResponse(null, json, null));
});
// no need to catch again. if userPromise is rejected, it will be handled by the catch above.
答案 2 :(得分:0)
我想一种实现相同代码的合理方式可能就像;
user.isExistingUser(email)
.then(successData => successData &&
successData.length === 0 ? user.signUp(signUpInfo)
.then(successData => emailService.sendVerificationEmail(recipientInfo))
.then(successData => res.json(responseUtility.getApiResponse(successData)))
: res.json(responseUtility.getApiResponse(null, [{param: 'email', msg: 'An account already exists with this email'}], null)))
.catch(err => res.json(responseUtility.getApiResponse(null, null, err)));