如何正确突破承诺链? [英] How to properly break out of a promise chain?

查看:131
本文介绍了如何正确突破承诺链?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于此处的问题: jQuery的链接和级联是在何时何地和已接受的答案,我想在某个时候打破承诺链,但尚未找到正确的方法.有多个 帖子 关于,但是我仍然迷路

Based on the question here: jQuery chaining and cascading then's and when's and the accepted answer, I want to break the promise chain at a point but haven't yet found the correct way. There are multiple posts about this, but I am still lost.

从原始问题中获取示例代码:

Taking the example code from the original question:

Menus.getCantinas().then(function(cantinas){ // `then` is how we chain promises
    Menus.cantinas = cantinas;
    // if we need to aggregate more than one promise, we `$.when`
    return $.when(Menus.getMeals(cantinas), Menus.getSides(cantinas));
}).then(function(meals, sides){ // in jQuery `then` can take multiple arguments
    Menus.sides = sides; // we can fill closure arguments here
    Menus.meals = meals;
    return Menus.getAdditives(meals, sides); // again we chain
}).then(function(additives){
    Menus.additives = additives;
    return Menus; // we can also return non promises and chain on them if we want
}).done(function(){ // done terminates a chain generally.
     // edit HTML here
});

如果cantinas.length == 0,我该如何打断链条?坦白说,我不想吃顿饭,也不想添加餐食,我想称呼某种空结果"回调.我尝试了以下非常难看的方法(但是可以...).教我正确的方法.这仍然是一个有效的结果,所以本质上不是失败",我会说是空的结果.

How would I break the chain if cantinas.length == 0? I would not want to get the meals, neither the additives, frankly I would want to call some kind of "empty result" callback. I have tried the following which is very ugly (but works...). Teach me the correct way. This still is a valid result, so not a "fail" per se, just empty result I would say.

var emptyResult = false;
Menus.getCantinas().then(function(cantinas){
    Menus.cantinas = cantinas;
    if (cantinas.length == 0) {
      emptyResult = true;
      return "emptyResult"; //unuglify me
    }
    return $.when(Menus.getMeals(cantinas), Menus.getSides(cantinas));
}).then(function(meals, sides){ 
    if (meals == "emptyResult") return meals;  //look at my ugliness...
    Menus.sides = sides;
    Menus.meals = meals;
    return Menus.getAdditives(meals, sides);
}).then(function(additives){
    if (additives == "emptyResult") return additives;
    Menus.additives = additives;
    return Menus;
}).done(function(){
   if (emptyResult)
     //do empty result stuff
   else
     // normal stuff
});

推荐答案

首先,我认为最好说的是您寻求绕过"承诺链(的一部分),而不是打破"承诺链.

Firstly, I think it better to say you are seeking to "bypass" (part of) the promise chain rather than to "break" it.

正如您所说,在多个地方测试"emptyResult"是非常丑陋的.幸运的是,在遵循不执行某些promise链的相同一般原则的同时,还可以使用更优雅的机制.

As you say, testing for "emptyResult" in several places is pretty ugly. Fortunately, a more elegant mechanism is available while adhering to the same general principle of not executing some of the promise chain.

另一种机制是使用承诺拒绝来控制流程,然后在链中稍后重新检测特定的错误情况,然后将其放回成功路径.

An alternative mechanism is to use promise rejection to control the flow, then to re-detect the specific error condition(s) later in the chain, and put it back on the success path.

Menus.getCantinas().then(function(cantinas) {
    Menus.cantinas = cantinas;
    if(cantinas.length == 0) {
        return $.Deferred().reject(errMessages.noCantinas);
    } else {
        return $.when(Menus.getMeals(cantinas), Menus.getSides(cantinas));
    }
}).then(function(meals, sides) {
    Menus.sides = sides;
    Menus.meals = meals;
    return Menus.getAdditives(meals, sides);
}).then(function(additives) {
    Menus.additives = additives;
    return Menus;
}).then(null, function(err) {
    //This "catch" exists solely to detect the noCantinas condition 
    //and put the chain back on the success path.
    //Any genuine error will be propagated as such.
    //Note: you will probably want a bit of safety here as err may not be passed and may not be a string.
    return (err == errMessages.noCantinas) ? $.when(Menus) : err;
}).done(function(Menus) {
    // with no cantinas, or with everything
});

var errMessages = {
    'noCantinas': 'no cantinas'
};

从好的方面来说,我发现缺少嵌套的做法可以使自然成功之路变得更具可读性.另外,至少对我来说,如果需要,这种模式将需要最少的心理干预以适应更多的绕行.

On the plus side, I find the lack of nesting makes for better readability of the natural success path. Also, for me at least, this pattern would require minimal mental juggling to accommodate further bypasses, if needed.

在不利的一面,这种模式的效率略低于Bergi的模式.主路径的承诺数量与Bergi的数量相同,而cantinas.length == 0路径则需要一个以上的数量(如果编码了多个旁路,则每个旁路需要一个).另外,这种模式要求可靠地重新检测特定的错误情况,因此可能会损害errMessages对象.

On the down side, this pattern is slightly less efficient than Bergi's. Whereas the main path has the same number of promises as Bergi's, the cantinas.length == 0 path requires one more (or one per bypass if multiple bypasses were coded). Also, this pattern requires reliable re-detection of specific error condition(s) - hence the errMessages object - which some may find detracts.

这篇关于如何正确突破承诺链?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆