Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a good way of short circuiting Javascript promises?

I'm a bit of a novice with promises/Deferreds. Is there a good pattern to handle the case where one might want to short circuit a chain of promises, for both success and error cases? In the error situation, I know you can chain a .then(null, function(error) {}) to the end and catch an error from any of the previous thens, but what if you want to handle an error in a more custom way and terminate? Would you specify a 'type' of error in an earlier error handler and return it via a new promise, to be handled or skipped in the final error handler? And what about a success case, where you want to terminate earlier in the chain (only conditionally firing off any later then's)?

like image 940
qix Avatar asked Nov 27 '13 09:11

qix


People also ask

Does promise all short circuit?

Regardless of settled (fulfilled or rejected) state, all promises resolve without short-circuiting to catch.

What is the problem with promises in Javascript?

Promises co-mingle rejected promises and unintended runtime exceptions. Apart from how the API is structured - promises have another major flaw: they treat unintentional native runtime exceptions and intentional rejected promises - which are two drastically different intentions - in the same "path".

What happens if you don't resolve a promise Javascript?

A promise is just an object with properties in Javascript. There's no magic to it. So failing to resolve or reject a promise just fails to ever change the state from "pending" to anything else. This doesn't cause any fundamental problem in Javascript because a promise is just a regular Javascript object.

Can promise be chained?

Example 2: Chaining the Promise with then() Promise resolved You can call multiple functions this way. In the above program, the then() method is used to chain the functions to the promise. The then() method is called when the promise is resolved successfully. You can chain multiple then() methods with the promise.


1 Answers

Typically, the promise chain starts with a call to some asynchronous function as such:

var promise = callAsync();

If you are chaining a second async call, you probably do something like this:

var promise = callAsync()
.then(function(){
    return callOtherAsync();
})
.then(function(){
    return callSuccessAsync();
}, function(){
    return callFailAsync();
});

As a result of chaining, promise now contains the final promise which completes when callFinalAsync()'s promise completes. There is no way to short circuit the final promise when using this pattern - you can return a failed promise along the way (for instance, rather than returning the result of callOtherAsync) but that requires the failed promise to progress through the chain (thus causing callFailAsync to be called). You can always fulfill or reject the promise from within the callbacks as such

var promise = callAsync()
.then(function(){
    if(fail){
        promise.reject();
        //no way to halt progression 
    }else{
        return callOtherAsync();
    }
})
.then(function(){
    return callSuccessAsync();
}, function(){
    return callFailAsync();
});

however, this will not prevent calls to callFailAsync(). Some Promise/A implementations expose a stop method for just this purpose. With stop, you could do this:

var promise = callAsync();
.then(function(){
    if(fail){
        this.stop(); 
        promise.reject();
    }else{
        return callOtherAsync();
    }
})
.then(function(){
    return callSuccessAsync();
}, function(){
    return callFailAsync();
});

Which depends on having access to the intermediate promise with this. Some Promise implementations forbid that (forcing this to be window/null/etc), but you can deal with that with a closure.

TL;DR: Promise/A spec doesn't provide a chain short circuit function, but it's not hard to add one.

like image 86
jordancpaul Avatar answered Nov 14 '22 22:11

jordancpaul