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

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

问题描述

基于这里的问题: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"非常难看.幸运的是,在遵循不执行某些承诺链的相同一般原则的同时,可以使用更优雅的机制.

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 的 promise 数量相同,但 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天全站免登陆