使用Promises纠正多路流的模式

yos*_*reb 6 javascript promise es6-promise

所以我过去几天一直在玩承诺,只是试图转换一些项目,使用承诺,但我已经多次修复这个问题.

在阅读文章和教程时,一切看起来都很流畅:

getDataFromDB()
.then(makeCalculatons)
.then(getDataFromDB)
.then(serveToClient)
Run Code Online (Sandbox Code Playgroud)

但实际上,它不是那样的.
程序有很多"if conditions"改变整个流程:

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(...
Run Code Online (Sandbox Code Playgroud)

我有两个主要问题:

  1. 我发现自己ifthen回调中添加了很多条件.
  2. 我仍然进入下一个then回调,即使我已经完成了(serveToClient)


我是否遵循了正确的模式?

jfr*_*d00 5

您无法避免这些if语句,因为逻辑流程需要这些语句.如果你不想在一部分中继续承诺链,你将不得不分支你的控制流if.因此,如果在第二个.then()处理程序的某些部分中,您不想继续使用第三个.then()处理程序,那么您需要像这样分支逻辑,并将后续.then()处理.then()程序放在它们自己的逻辑分支中的第二个处理程序中.

你不能只是继续顶级分支,因为.then()在主链中中止未来逻辑的唯一方法是拒绝承诺(你可能不想做)或if在每个.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
});
Run Code Online (Sandbox Code Playgroud)

您可能会发现这些其他答案很有用:

理解javascript承诺; 堆叠和链接

promise.then.then与promise.then之间有区别吗?promise.then


仅供参考,你可以重新组织上面的代码,使其更简洁:

getDataFromCache().then(function(result) {
    if (result)
        serveToClient();
    } else {
        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
});
Run Code Online (Sandbox Code Playgroud)

  • @yosiweinreb - 您只需要与逻辑需要一样多的缩进级别.对于严格的顺序执行,您只需要一个长链而不需要额外的嵌套.每当你想用`if`语句分支你的链时,你必须添加一个嵌套级别.想想看,它与同步编程并没有什么不同.如果在同步编程中添加一个不希望继续其余逻辑的`if`,那么你也可以在那里添加一个嵌套级别.当你开始弄清楚如何处理错误条件时,承诺将比回调更好. (2认同)