Promise anti-patterns
Explanation of common anti-patterns to avoid when using promises in JavaScript
In this lesson, we will discuss common promise-related anti-patterns that should be avoided. Following is a list of anti-patterns we will discuss:
Unnecessary use of the Promise constructor
Incorrect error handling
Converting promise rejection into fulfillment
Async executor function
Unnecessary use of the Promise Constructor#
One of the most common mistakes made by JavaScript developers, especially those who don't have much experience with promises, is creating promises unnecessarily using the Promise
constructor function. Let's take a look at an example:
xxxxxxxxxx
function fetchData(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then((res) => res.json(res))
.then(resolve)
.catch(reject);
});
}
The above code will work if you pass a URL to the fetchData
function and then wait for the promise to resolve, but the use of the Promise
constructor is unnecessary in the above code example. The fetch
function already returns a promise, so instead of wrapping the fetch
function call with the promise constructor, we can re-write the above function as shown below:
xxxxxxxxxx
function fetchData(url) {
return fetch(url).then((res) => res.json(res));
}
The revised version of the fetchData
function is concise, easy to read, free from the creation of any unnecessary promises, and allows the code that calls the fetchData
function to catch and handle any errors. The older version of the fetchData function also allowed the calling code to handle errors, but the revised version does it without using the catch method call.
Unnecessary use of the promise constructor can lead to another problem: if we forget to add the catch
method call to the promise chain inside the Promise
constructor, then any error thrown during the HTTP request won't be caught. Forgetting to call the reject
function inside the executor function can hide the failure of the asynchronous operation inside the executor function.
Incorrect Error Handling#
When writing code that uses promises, one of the most important rules to keep in mind is to either catch and handle the error or return the promise to allow the calling code to catch and handle it. This fundamental rule can help you avoid hidden bugs in the code that uses promises.
Let's take a look at an example of incorrect handling of errors that breaks the above rule:
xxxxxxxxxx
function fetchData(url) {
fetch(url).then((response) => response.json());
}
​
fetchData("https://jsonplaceholder.typicode.com/todos/1")
.then((data) => console.log(data))
.catch((error) => console.log(error));
Here's a Replit of the above code in action:
The above code throws an error because the fetchData
function doesn't return the promise. It also doesn't allow the calling code to do any kind of error handling.
There are two ways to fix the above code:
This lesson preview is part of the Advanced JavaScript Unleashed course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Advanced JavaScript Unleashed, plus 70+ \newline books, guides and courses with the \newline Pro subscription.
