How to properly break out of a promise chain?

后端 未结 3 1376
忘了有多久
忘了有多久 2020-11-22 06:12

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 fo

3条回答
  •  心在旅途
    2020-11-22 06:28

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

    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.

    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.

提交回复
热议问题