What is a promise?
A promise is an object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. It allows you to write asynchronous code in a more manageable way, avoiding callback hell.
How does a promise work?
A promise has three states:
- Pending: The initial state, neither fulfilled nor rejected.
- Fulfilled: The operation completed successfully, and the promise has a resulting value.
- Rejected: The operation failed, and the promise has a reason for the failure (an error).
When a promise is fulfilled or rejected, it can trigger callbacks that were registered to handle those outcomes.
Creating a promise
You can create a promise using the Promise
constructor. Here's the basic structure of a promise:
/*
resolve and reject are callback functions.
On success(fulfillment), run resolve() with the result. The result can be retrieved later in the `then` method.
On failure(rejection), run reject() with an error. The error can be retrieved later in the `catch` method.
*/
const myPromise = new Promise((resolve, reject) => {
const success = true; // Simulate success or failure
if (success) {
resolve("Promise resolved successfully!");
} else {
reject("Promise failed!");
}
});
Using promise
With the then
and catch
methods
Once you have created a promise, you can use the then
and catch
methods to
handle the result of the promise.
- The
then
method is called when the promise is fulfilled, - and the
catch
method is called when the promise is rejected.
// I used myResult and myError to prove that names can be changed to whatever you want.
myPromise
.then((myResult) => {
console.log(myResult); // "Promise resolved successfully!"
})
.catch((myError) => {
console.error(myError); // "Promise failed!"
})
.finally(() => {
console.log("Promise has settled (either resolved or rejected).");
});
Why use finally()
?
The finally()
method is useful for cleanup tasks that need to run regardless of the promise's outcome, such as:
- Hiding a loading spinner.
- Closing a database connection.
- Logging that an operation has completed.
With async/await
You can also use async/await
syntax to work with promises, which makes the code look more synchronous:
async function main() {
try {
const result = await myPromise;
console.log(result); // "Promise resolved successfully!"
} catch (error) {
console.error(error); // "Promise failed!"
}
}
main();
Calling asynchronous function inside a promise
Calling fetch() using then
and catch
method
const myPromiseFetch1 = new Promise((resolve, reject) => {
const url = "https://jsonplaceholder.typicode.com/posts/1"; // Example API endpoint
fetch(url)
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json(); // Parse JSON response
})
.then((data) => {
resolve(data); // Resolve the promise with the fetched data
})
.catch((error) => {
reject(error); // Reject the promise with the error
});
});
myPromiseFetch1
.then((data) => {
console.log("Fetched Data:", data); // Output the fetched data
})
.catch((error) => {
console.error("Fetch Error:", error); // Output the error
})
.finally(() => {
console.log("Fetch operation completed.");
});
Calling fetch() using async/await
const myPromiseFetch2 = new Promise(async (resolve, reject) => {
const url = "https://jsonplaceholder.typicode.com/posts/1"; // Example API endpoint
try {
const response = await fetch(url); // Await the fetch call
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json(); // Await the JSON parsing
resolve(data); // Resolve the promise with the fetched data
} catch (error) {
reject(error); // Reject the promise with the error
}
});
myPromiseFetch2
.then((data) => {
console.log("Fetched Data:", data); // Output the fetched data
})
.catch((error) => {
console.error("Fetch Error:", error); // Output the error
})
.finally(() => {
console.log("Fetch operation completed.");
});
Chaining promises
You can chain multiple promises together using the then
method. Each then
returns a new promise, allowing you to perform additional asynchronous operations in sequence:
myPromise
.then((result) => {
console.log(result);
return new Promise((resolve) => {
setTimeout(() => resolve("Second operation completed!"), 1000);
});
})
.then((secondResult) => {
console.log(secondResult); // "Second operation completed!"
})
.catch((error) => {
console.error(error.message);
});
Promise.all
You can use Promise.all
to run multiple promises in parallel and wait for all of them to complete:
const promise1 = new Promise((resolve) => setTimeout(() => resolve("First"), 1000));
const promise2 = new Promise((resolve) => setTimeout(() => resolve("Second"), 2000));
const promise3 = new Promise((resolve) => setTimeout(() => resolve("Third"), 1500));
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results); // ["First", "Second", "Third"]
})
.catch((error) => {
console.error(error.message);
});