krulik krulik - 3 months ago 14
Javascript Question

How to early exit a composition of Promises

I'd like to do something like this:

return1stPromise()
.then(if1stPromiseSucceeds) // returns 2nd Promise
.catch(if1stPromiseFails)
.then(if2ndPromiseSucceeds) // execute only if 1st Promise succeeds


I'd like the 2nd
.then
to execute only if 1st Promise succeeds. Or in different words - I don't want the 2nd
.then
to execute if the catch has been executed.

Is this even possible or do I have nest the 2nd promise inside the first
then
like this:

return1stPromise()
.then(function (data) {
return if1stPromiseSucceeds(data).then(if2ndPromiseSucceeds);
})
.catch(if1stPromiseFails);


In addition - any good resources on how to control flow with Promises where it's more thread like?

Answer

What you are describing is typically the case when we want to react to an exception but not actually handle it and let the code keep running:

return1stPromise()
  .then(if1stPromiseSucceeds) // returns 2nd Promise
  .catch(() => { if1stPromiseFails(); throw e; })
  .then(if2ndPromiseSucceeds) // execute only if 1st Promise succeeds

You need to rethrow the exception in order to mark it as "still not handled".

This is like synchronous code:

try {
  var res = firstResult();
  var res2 = ifFirstPromiseSucceeds(res);
} catch (e) {
    ifFirstPromiseFails();
    throw e; // we reacted to the exception but did not handle it yet.
}
var res3 = ifSecondPromiseSucceeds();

I think thinking of promises in terms of threads is mostly confusing - finding a synchronous analogy is always easier if possible.

It's not always possible, for example another way to stop a promise chain in the way is cancellation which is a little like a thread abort with "I don't care about the results" semantics - you can read about it here but I think for your use case it's a little over the top and not as nice.