|jQuery 3 - Consuming Promises|
|Written by Ian Elliot|
|Thursday, 06 July 2017|
Page 4 of 4
Promise Error Handling
One of the big advantages of using promises is that they make error handling easier. Not easy, but easier. Asynchronous error handling is never easy because errors can occur in in a function while other functions are still executing. There is generally no way of cancelling asynchronous functions and this can make it difficult to work out what to do. However the main problem promises solve is detecting when something has gone wrong.
We already know that you can specify an error handler as part of the then function.
The handleError function will be called if the get fails for any reason i.e. if it returns an error status.
This is simple but things get a little more complicated when we have a chain of thens. If you are running one asynchronous task after another then we have already discovered that you can do this by a chaining thens.
where chaining has been avoided to show the explicit promises returned. The first then returns promise2 that is settled when onSucess1 returns a value or a settled promise.
It is also helpful to keep in mind that in say:
It is the settlement state of promise1 that determines which of onSucess1 or onFailure1 are executed and what onSucess1 or onFailure1 return that determines the settlement state of promise2.
However there is an additional rule governing chained promises. If there is no onSucess or onFailure to handle the settlement of the promise then that state is passed to the next promise and so on until there is handler for the state.
That is an unhandled state is passed to the next promise in the chain.
This intentionally copies the way that exceptions work in synchronous code.
So for example if we have, writing the chain out in full for clarity:
and promise1 is fulfilled there is no onSucess handler defined in its then. What happens is that this state is passed to promise2 which is fulfilled and onSucess2 is executed. Notice that the final state of promise2 would have been determined by the missing onSucess1 handler so passing the state on is reasonable as a default.
The same rule applies to the rejection handlers. If there is no rejection handler and the promise is rejected then that state is passed to the next handler in the chain.
Once the state has found a handler then processing resumes its normal course.
But to make sense of "normal course" we need one final rule.
Any handler that returns a value and does not throw an error passes on a success to the next promise and this includes onFailure handlers. Any handler that throws an exception passes a reject on to the next promise.
This all seems complicated but the rule is that states are passed on if there is no handler for the state and any handler that returns a value and doesn't throw an exception passes on a success to the next promise.
which would normally be written:
Suppose promise1 is rejected then as it has no onFailure handler the rejection is passed on to promise2 which causes onFailure2 to run. Assuming onFailure2 returns a value and doesn't throw an exception then promise3 is fulfilled and onSucess3 runs. You can think of this as a successful run of onFailure2 keeps the sequence of operations going. If this isn't what you want then throw an exception in onFailure1.
In most cases it is reasonable to leave any rejection of any promise in a chain of promises till the very end so aborting the chain.
If any of the promises are rejected then the subsequent tasks are not started and the next function to be executed in onFailure4 which is a catch all error routine.
This is such a common idiom that there is a special catch function which just sets a reject handler. So you could write the above as:
Of course even this isn't the usual way to write this because we use chaining:
which now looks a lot more like the synchronous try-catch block that it models. To be clear if there is a problem in any of the tasks say in onSucess2 then effectively control jumps straight to onFailure4.
There are lots and lots of situations that you can use promises in that we haven't looked at. A general programming feature like promises are capable of very varied use and a full catalogue is very likely impossible. However if you understand how they work then you should be able to work out how promises behave in any given situation.
or email your comment to: firstname.lastname@example.org