Promises Error Handling
Introduction
One of the biggest concerns of complex applications, be they for web or desktop, is to handle errors effectively.
This requires the use of the conventional try..catch
statements bundled with the throw
keyword; in addition to listening for error
events, laying out numerous if
checks in the code and much more on this way.
Sometimes it also requires passing in callbacks to be fired on the occurrence of any errors. When this is the case and the overall code is quite involved, then using a callback simply means to be writing code that will ultimately lead to unmanageable clutter - as discussed in detail in the Promises Introduction chapter.
What's rather a better alternative is to use a promise!
In this chapter we shall introduce you to the catch()
method inherited by all promises and see how it's analogous to the second argument to then()
, and how to use all these features to handle bugs occurring in the wrapped-up asynchronous operation.
Let's begin!
What is error handling?
We'll start by answering the question - what is error handling - using our all-time favourite example i.e AJAX.
Suppose you make a request to some random file on your server using XMLHttpRequest()
- the core of AJAX. What errors do you think can possibly occur in the whole request-response cycle?
Do this as a quick exercise - it will give you a good warmup on the topic!
To name a few:
The request can be made to a non-existent file in which case the server would send a 404, Not Found, status code.
The server script at the backend might have an invalid syntax in which case it would response with a 500 Internal Server Error, status.
The client's network could be down in which case the
error
event would be dispatched.The request can violate the CORS policy in which case, once again, the
error
event will be fired.
and so on....
Actually, it depends on the application itself - for example it can be configured to parse a JSON response and then read a property on the parsed object to determine the status of the response.
Whatever the case be, the main point over here is that errors can happen in any asynchronous operation and thereby it's imperative for us to write code that handles them effectively.
How to handle errors? Well it's pretty elementary!
Error handling in JavaScript is usually done with two things: events and conditional statements.
Events such as error
and abort
frequently fire, even in simplistic applications; likewise it's common to provide onerror
and onabort
handlers to eventually respond to each case.
Similarly, often times one needs to lay out conditional checks in order target errors - for example by checking the status
property of an XMLHttpRequest()
object against the value 200
in the load
event, we can throw an exception once we know it's not equal to 200
.
As another example: we can check for the availability of the XMLHttpRequest()
API and consequently throw an exception if it's not suported.
So now that we know how to handle errors in programming, it's finally time that we dive right into implementing it in promises.
Home > Courses > Advanced JavaScript > Promises - Error Handling
Promises Error Handling
What will you learn in this page?
What is error handling
How to handle errors in JavaScript
The
onRejected()
callbackThe
catch()
method
PromisesChaining QuizBuffersBasics
Introduction
One of the biggest concerns of complex applications, be they for web or desktop, is to handle errors effectively.
This requires the use of the conventional try..catch
statements bundled with the throw
keyword; in addition to listening for error
events, laying out numerous if
checks in the code and much more on this way.
Sometimes it also requires passing in callbacks to be fired on the occurrence of any errors. When this is the case and the overall code is quite involved, then using a callback simply means to be writing code that will ultimately lead to unmanageable clutter - as discussed in detail in the Promises Introduction chapter.
What's rather a better alternative is to use a promise!
In this chapter we shall introduce you to the catch()
method inherited by all promises and see how it's analogous to the second argument to then()
, and how to use all these features to handle bugs occurring in the wrapped-up asynchronous operation.
Let's begin!
What is error handling?
We'll start by answering the question - what is error handling - using our all-time favourite example i.e AJAX.
Suppose you make a request to some random file on your server using XMLHttpRequest()
- the core of AJAX. What errors do you think can possibly occur in the whole request-response cycle?
Do this as a quick exercise - it will give you a good warmup on the topic!
To name a few:
The request can be made to a non-existent file in which case the server would send a 404, Not Found, status code.
The server script at the backend might have an invalid syntax in which case it would response with a 500 Internal Server Error, status.
The client's network could be down in which case the
error
event would be dispatched.The request can violate the CORS policy in which case, once again, the
error
event will be fired.
and so on....
Actually, it depends on the application itself - for example it can be configured to parse a JSON response and then read a property on the parsed object to determine the status of the response.
Whatever the case be, the main point over here is that errors can happen in any asynchronous operation and thereby it's imperative for us to write code that handles them effectively.
How to handle errors? Well it's pretty elementary!
Error handling in JavaScript is usually done with two things: events and conditional statements.
Events such as error
and abort
frequently fire, even in simplistic applications; likewise it's common to provide onerror
and onabort
handlers to eventually respond to each case.
Similarly, often times one needs to lay out conditional checks in order target errors - for example by checking the status
property of an XMLHttpRequest()
object against the value 200
in the load
event, we can throw an exception once we know it's not equal to 200
.
As another example: we can check for the availability of the XMLHttpRequest()
API and consequently throw an exception if it's not suported.
So now that we know how to handle errors in programming, it's finally time that we dive right into implementing it in promises.
Rejection callback
Recall the then()
method and the callback arguments we provide to it: the first one is the onFulfilled
callback which fires once the promise is fulfilled while the second one is the onRejected
callback which fires once the promise is rejected.
If onRejected
is provided; well and good, but if it's not, then the default "Thrower"
argument is taken to be the callback.
The question is that when does a given promise get rejected!
Well there are two ways to reject a promise: one is by invoking the reject()
callback passed to the executor whereas the other is by throwing an exception explicitly inside the executor, using the throw
keyword.
The way the latter works is described as follows:
When the Promise()
constructor is instantiated, it immediately executes the provided executor function, inside a try
block - much like the code below:
The corresponding catch
block calls the same reject()
function passed to the executor, and supplies it with the error argument e
, as shown above.
This means that any thrown exceptions inside the executor will cause the corresponding promise to be rejected with the thrown value.
Let's consider a couple of examples.
Following is the code to illustrate promise rejection, done by explicitly calling the reject()
argument:
Here if we log the promise object p
after 3 seconds, we'll get something similar to the following:
Promise {<rejected>: "Sorry"}
If we want we can also pass in a callback to then()
to handle the promise's rejection after 3 seconds. This is shown below:
The second argument here is an anonymous function that logs an error message in the console, when invoked roughly after 3 seconds.
An error occurred: SorryRecall that it's the second argument to then()
that deals with errors; NOT the first one, which in this case is set to null
(it isn't required for the example and so there's no point of giving one).
Now for the second case - throwing an exception explicitly within the promise - consider the code below:
Although it's different syntactically, this code does exactly the same thing as the one shown above with reject()
. When the statement throw "Sorry"
is executed, control flow shifts to the internal catch
block, which then calls the reject()
function with the throw value "Sorry"
.
Once again, we can attach a failure callback to the promise p
here, which'll operate exactly the same as in the previous example.
An error occurred: Sorry
Moving on, as we know from the previous chapter on Promise Chaining, then()
returns a promise which depends on the respective passed-in callback to complete.
In the occasion where it throws an error itself, the returned promise is rejected with the thrown value.
Consider the code below:
Promise {<rejected>: "Sorry"}
See how the main promise p
is resolved but the one derived by calling then()
i.e p2
, is rejected - simply because the callback throws an error.
A derived promise is rejected with value v
, if an exception v
is thrown in the corresponding then()
's callback.
On the same lines, we can also return a promise in the callback that gets rejected eventually and thus causes the derived promise to get rejected as well:
If we log p2
after a while over here, we'll get something similar to the following:
Promise {<rejected>: "Sorry"}
This happens because when a then()
callback returns a promise itself, the corresponding derived promise mimics that returned promise - in this case p2
mimics the promise in line 7.
Now retreating back to the scenario where an explicit exception is thrown inside the callback for then()
, we have an amazing concept following from this very basic idea, which we're about to explore next.
First of all it's vital for us to understand that if we don't provide a failure callback to then()
, the method will default it to the "Thrower"
function - which will simply throw an exception with the value of the promise.
Consider the code below:
This is the same as writing the following (with the second argument to then()
omitted this time):
For more info on the default arguments to then()
, please read Promises Basics.
With this understood, try to solve the task below and see how well have you learnt promises overall!
Last updated