Why is this an issue?
In JavaScript, a promise is an object representing the eventual completion or failure of an asynchronous operation. It is a way to handle
asynchronous operations more elegantly and avoid the "callback hell".
A promise can be in one of three states:
- Pending: The initial state of a promise. It represents that the asynchronous operation is still ongoing and has not yet been fulfilled or
rejected.
- Fulfilled: The state of a promise when the asynchronous operation has been successfully completed. It represents that the promised value is
available and can be consumed.
- Rejected: The state of a promise when the asynchronous operation encounters an error or fails to complete. It represents that an error has
occurred and the promised value is not available.
The basic syntax for creating a promise in JavaScript is as follows:
const myPromise = new Promise((resolve, reject) => {
// Asynchronous operation
// If the operation is successful, call resolve(value)
// If the operation fails, call reject(error)
});
However, when it comes to immediately resolving or rejecting states, creating a new promise with the Promise
constructor and manually
calling resolve
or reject
makes the code verbose and more difficult to read.
const result = new Promise(resolve => resolve(42)); // Noncompliant: Redundant to explicitly create a promise to resolve 42
result.then(value => {
console.log(value); // Output: 42
});
Instead, a promise can be created with Promise.resolve
. It is typically used when you want to create a new promise that is already
resolved with a certain value. It is commonly used to wrap synchronous values or functions into promises.
How to fix it
If you already have a synchronous value that you want to convert into a promise, using Promise.resolve
is more concise and
straightforward. It immediately creates a promise that is already resolved with the provided value.
const result = Promise.resolve(42);
result.then(value => {
console.log(value); // Output: 42
});
Similarly, if you have an error or an exceptional condition and want to create a promise that is immediately rejected with that error, using
Promise.reject
is more straightforward. It creates a promise in the rejected state with the provided error.
const error = new Error('Something went wrong');
const promise = Promise.reject(error);
If you have a condition and want to create a promise that is either resolved or rejected based on that condition, using
Promise.resolve
or Promise.reject
helps make the code more readable and concise.
function fetchData() {
if (cache) {
return Promise.resolve(cache);
} else if (shouldFetchData()) {
return fetchDataFromServer()
.then(data => {
cache = data;
return data;
});
} else {
return Promise.reject(new Error('Data fetch is not required'));
}
}
When you have a promise chain and want to introduce an intermediate step with an immediately resolved value, using Promise.resolve
allows you to continue the chain without introducing unnecessary complexity.
const data = cache ? cache : fetchData();
return Promise.resolve(data) // data may be a Promise or not, we need to wrap it
.then(data => {
return sanitizeData(data);
})
Using Promise.resolve
and Promise.reject
is particularly useful when you want to simplify the creation of promises with
immediately resolved or rejected states. They provide a cleaner and more direct approach compared to creating a new promise with the
Promise
constructor and manually calling resolve
or reject
.
Resources
Documentation