Easily restore your project to a previous version with our new Instant One-click Backup Recovery

How to handle an Unhandled Promise Rejection in JavaScript

The states of JavaScript promises can be pending, fulfilled, or rejected. Let's take a look at what you should do when there is an "unhandled promise rejection".
Joel Olawanle

Joel Olawanle

Feb 07, 2023
How to Handle an Unhandled Promise Rejection in JavaScript

The states of JavaScript promises can be pending, fulfilled, or rejected. Let's look at what you should do when there is an "unhandled promise rejection".

#What is a Promise?

A Promise is a special JavaScript object representing an asynchronous operation's eventual fulfillment or failure. It is similar to making a promise in real life, where you promise to do something in the future. A promise always has two outcomes: you either do it by keeping your Promise or you do not.

JavaScript promises are complex but straightforward to grasp. A promise object has two properties: state and result. The state can be pending, fulfilled, or rejected; the result can be undefined or the value of the fulfilled or rejected state.

undefined

  • Pending: This is the initial state of the promise when it is being processed. This is the initial state before the promise succeeds or fails and has a result of undefined.
  • Fulfilled: This is the completed and successful state of a promise. It returns the resolve value as a result.
  • Rejected: Like the resolved or fulfilled states, the rejected state indicates a failed promise. If a promise ends up in the rejected state, the error value is returned as a result.

In clear terms, the promise state is initially pending with a result of undefined; when the Promise's condition is true, the state is fulfilled and has a result with the value of resolve(value); otherwise, when the condition fails, it has an error value of reject (error).

undefined

For example, the code block below is a Promise that checks a condition. If the condition is true it resolves otherwise, it rejects.

const myPromise = new Promise((resolve, reject) => {
let cms = "Hygraph";
if (cms === "Hygraph") {
resolve("Success: The promise has successfully resolved!");
} else {
reject("Failure: The promise has failed!");
}
});

Editor's Note

A promise that is either resolved or rejected is called settled.

#How to use Promises

function getUsersPromise() {
const DUMMY_USERS_DATA = [{ id: 1, name: "John Doe" }];
return new Promise((resolve, reject) => {
// Fake success
setTimeout(() => {
resolve(DUMMY_USERS_DATA);
}, 1000);
// Fake Error
// setTimeout(() => {
// reject("something went wrong...");
// }, 1000);
});
}

The getUsersPromise function returns a promise that simulates fetching user data. The promise uses setTimeout to delay the resolution by 1 second. When resolved, it returns the DUMMY_USERS_DATA array. There is also a commented-out section that, if uncommented, would simulate an error by rejecting the promise with the message "something went wrong..." after 1 second.

We can simply use a .then() handler method to consume a promise.

function getUserList() {
return getUsersPromise().then((data) => data);
}

We can also use async await syntax as well to consume a promise.

async function getUserList() {
return await getUsersPromise();
}

#How to handle unhandled Promise rejections

Many things can get a promise rejected, such as some run time error or a network failure.

When an error arises within a promise, it gets rejected and calls the reject() function. Unhandled promise rejections imply that when a promise is rejected, it is not handled. In other words, it is unhandled because nothing deals with the rejection.

For example:

function getUsersPromise() {
const DUMMY_USERS_DATA = [{ id: 1, name: "John Doe" }];
return new Promise((resolve, reject) => {
// Fake Error
setTimeout(() => {
reject("something went wrong...");
}, 1000);
});
}
async function getUserList() {
return await getUsersPromise();
}
// OR
// function getUserList() {
// return getUsersPromise().then((data) => data);
// }
getUserList();

Above is a promise that fails, for simplicity, we have faked and called the reject() function after a delay of 1s. Okay but, what is the big deal about rejected promises and what exactly is an unhandled promise rejection?

The promise getUsersPromise in the above code is called by the getUserList function, the main issue here is that if the promise rejects which it will, no code is handling the promise rejection in the getUserList function. This would generate an “Unhandled Promise Rejection” error. This error can bubble up to your application root and can even stop your entire application.

Also, this is not just applicable to frontend Javascript code, but also to backend Node.js-based codebases.

For example, check this demo video:

In this demo, we have two different routes in a Node.js-based Express application.

  • GET /hello
  • GET /user

If you notice we hit the /hello endpoint that says Hello World. Once we hit the /user with an unhandled promise, our entire backed app crashes! Our rejected promise had nothing to do with the /hello endpoint, but it still went down as the app itself crashed. This can be really dangerous in production.

#How to handle Promises correctly

To handle promise rejections specifically, we can use the .catch() handler method. A more popular option is to wrap the promise call in a try-catch block.

// Using .catch() handler
function getUserList() {
return getUsersPromise()
.then((data) => data)
.catch((err) => console.error(err));
}
// Using a try-catch wrapper
async function getUserList() {
try {
return await getUsersPromise();
} catch (err) {
console.error(err);
}
}

That’s as simple as it could be.

Let us also explore an example using the Fetch API. The Fetch API is a built-in JavaScript method for retrieving resources and interacting with your backend server or an API endpoint. It returns a promise, meaning you can use the .then() and .catch() handler methods.

Let’s retrieve data by sending a GraphQL request with Fetch API to the Cocktails Hygraph content repository which holds some cocktails and some information about each cocktail:

fetch("https://api-us-east-1.hygraph.com/v2/cl4ji8xe34tjp01yrexjifxnw/master", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query: `
query {
cocktails {
category
info
ingredients
instructions
name
}
}
`,
}),
})
.then((response) => console.log(response.json()));

In the above example, rejection is not handled. In a Fetch API request, the Promise can be rejected due to network issues, permission issues, and other run time reasons. We can attach a catch handler to it to catch any unforeseen issues, as shown below:

fetch("https://api-us-east-1.hygraph.com/v2/cl4ji8xe34tjp01yrexjifxnw/master", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query: `
query {
cocktails {
category
info
ingredients
instructions
name
}
}
`
})
})
.then((response) => console.log(response.json()))
.catch((error) => console.log(error));

Or, we can also use the more popular async await option to have a more friendly syntax.

try {
const response = await fetch(
"https://api-us-east-1.hygraph.com/v2/cl4ji8xe34tjp01yrexjifxnw/master",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query: `
query {
cocktails {
category
info
ingredients
instructions
name
}
}
`,
}),
}
);
console.log(response.json());
} catch (err) {
console.log(err);
}

#Wrapping up

In this article, you have learned what are promises, how to use them. We also saw what exactly is an unhandled promise rejection and how dangerous it can be. Finally, we went through how to handle promises the correct way and saw examples around it.

Feel free to customize and handle rejections of promises however you'd like, but always make sure to handle rejections of promises when working with promises since your web application may run into run-time errors.

Blog Author

Joel Olawanle

Joel Olawanle

Joel Olawanle is a Frontend Engineer and Technical writer based in Nigeria who is interested in making the web accessible to everyone by always looking for ways to give back to the tech community. He has a love for community building and open source.