Is There A Good Way Of Short Circuiting Javascript Promises?
Solution 1:
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(){
returncallOtherAsync();
})
.then(function(){
returncallSuccessAsync();
}, function(){
returncallFailAsync();
});
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{
returncallOtherAsync();
}
})
.then(function(){
returncallSuccessAsync();
}, function(){
returncallFailAsync();
});
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{
returncallOtherAsync();
}
})
.then(function(){
returncallSuccessAsync();
}, function(){
returncallFailAsync();
});
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.
Solution 2:
not sure about jQuery but at least in any Promises/A+ you can just throw:
.then(function() {
if (skip) {
throw new Error("skipping");
}
})
//Chain of thens.then(...)
.then(...)
.then(...)
.then(...)
.catch(function(){
//skipped here
});
Solution 3:
I assume your use case looks like:
promise
.then(a)
.then(b); // We want to have an option to break here.then(c)
.done(d)
Logical way to handle this is:
promise
.then(a)
.then(function (result) {
if (something) throw new Error("Do not proceed!");
return b(result).then(c).then(d);
}).done();
If you don't like nesting, you may compose b(result).then(c).then(d)
as outer function.
Solution 4:
I had this exact problem in my application, and achieved short-circuit/cancellation through use of a simple cancellation token object that can be checked for in a Promise's exception/rejection handler callback. Maybe not the most elegant solution, but seems to work well enough without the need for additional libraries or alternate/non-standard Promise implementations
const cancellationToken = {};
somePromiseReturningMethod(...)
.then(doSomething)
.then(doSomethingElse)
.catch(err => {
if (err === cancellationToken)
{
// handle cancellation here and return
}
// handle "regular" errors here (show/log a message, etc)
});
functiondoSomething(dataFromPromise)
{
// check for whatever condition should result in cancellation/short-circuitif (...)
{
returnPromise.reject(cancellationToken);
}
// carry on as normal...
}
Post a Comment for "Is There A Good Way Of Short Circuiting Javascript Promises?"