所以我过去几天一直在玩承诺,只是尝试转换一些项目,使用承诺,但我已经多次担心这个问题。
在阅读文章和教程时,一切看起来都很流畅:
getDataFromDB()
.then(makeCalculatons)
.then(getDataFromDB)
.then(serveToClient)
但实际上,它不是那样的。
如果有条件,节目有很多"这改变了整个流程:
getDataFromCache(data).then(function(result){
if(result){
return result;
}else{
return getDataFromDB();
}
}).then(function(result){
if(result){
serveToClient() //this does not return a promise, so undefined returned...
}else{
return getDataFromWebService(); //this does return a promise,
}
}).then(function(result){
//i dont want to reach here if i already serveToClient()...
//so i basically have to check "if(result)" for all next thens
if(result){
//do more stuff
}
}).then(...
我有两个主要问题:
if
回调中添加了很多then
条件。then
)serveToClient
回调
醇>
我是否遵循了正确的模式?
答案 0 :(得分:5)
您无法避免if
语句,因为逻辑流程需要这样做。如果您不想在if
的某个部分继续保护链,则必须分支您的控制流。因此,如果在第二个.then()
处理程序的某些部分,您不想继续使用第三个.then()
处理程序,那么您需要像这样分支逻辑并放置后续{{1第二个.then()
处理程序内部的处理程序在它们自己的逻辑分支中。
您不能继续使用顶级分支,因为在主链中中止未来.then()
逻辑的唯一方法是拒绝承诺(您可能不想做) )或在每个.then()
处理程序中添加另一个if
检查,以决定是否应该跳过它(yuck)。
相反,您可以像这样分支逻辑:
.then()
您可能会发现这些其他答案很有用:
Understanding javascript promises; stacks and chaining
Is there a difference between promise.then.then vs promise.then; promise.then
仅供参考,你可以重新组织上面的代码,使其更简洁:
getDataFromCache().then(function(result){
if(!result) {
return getDataFromDB()
} else {
return result;
}
}).then(function(result){
// branch promise chain here into two separate branches
if(result){
// do not continue the promise chain here
// call a synchronous operation
serveToClient();
} else {
// continue promise chain here
return getDataFromWebService().then(function(result) {
if(result){
//do more stuff
}
}).then(...); // you can continue the promise chain here
}
}).catch(function(err) {
// process any errors here
});
答案 1 :(得分:2)
另一个答案解释了分支,但你也要求“顺利和干净”。
您可以使用ES6 arrow functions:
getDataFromCache()
.then(result => result || getDataFromDB())
.then(result => result ? serveToClient() : getDataFromWebService()
.then(result => { /* Won't reach here if serveToClient */ }))
.then(() => { /* can continue promise chain here */ })
.catch(e => console.log(e));
请注意,缩进的.then
位于getDataFromWebService()
,并且会看到尾部的双))
。这很好地反映了同步分支。
您可以使用ES8 async
/ await
(现已在Chrome Canary和Firefox Nightly中提供!):
try {
if (await getDataFromCache() || await getDataFromDB()) {
serveToClient();
} else {
let result = await getDataFromWebService();
/* Won't reach here if serveToClient */
}
/* can continue here */
} catch (e) {
// process any errors here
}
后者让你完全控制,好像事情是同步的,只要它在async
functions内。