JavaScript Promises - Complete Guide
Understanding JavaScript Promises, async operations, and Promise methods like all, race, any for handling asynchronous programming
Promise is a feature introduced in ES6 that provides built-in methods including all, race, resolve, reject, and others to handle asynchronous operations.
Promise Constructor
The Promise object constructor syntax is as follows:
let promise = new Promise(function(resolve, reject) {
// executor function
});
- resolve(value): Called when the operation completes successfully with a result value
- reject(error): Called when an error occurs, with error as the error object
When
new Promiseis declared, the executor function runs automatically. If execution is successful,resolveis called; if an error occurs,rejectis called.
Promise States and Results
The promise object returned by the new Promise constructor has the following internal properties:
- state — Initially “pending”, then changes to “fulfilled” when resolve is called, or “rejected” when reject is called
- result — Initially undefined, then becomes the value when resolve(value) is called, or the error when reject(error) is called
Important: The executor can only call one resolve or one reject:
let promise = new Promise(function(resolve, reject) {
resolve("done");
reject(new Error("...")); // ignored - first call wins
});
Handling Promise Results
.then()
The .then() method accepts two function parameters:
- First parameter: Function executed when promise resolves
- Second parameter: Function executed when promise rejects
promise.then(
function(result) { /* handle successful result */ },
function(error) { /* handle error */ }
);
.catch()
For error handling specifically:
promise.catch((error) => {
// handle error
});
Promise Static Methods
Promise.all()
let promise = Promise.all(iterable);
Executes multiple promises and waits for ALL promises to complete. If any promise rejects, the result is that rejection error.
Promise.all([
new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3
]).then((values) => console.log(values));
// Output: [1, 2, 3] (after 3 seconds)
Promise.all([
new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
new Promise((resolve, reject) => setTimeout(() => reject(new Error('error')), 1000)) // 3
]).catch((error) => console.log(error));
// Output: Error: error (after 1 second)
Promise.race()
Waits only for the FIRST settled promise and returns its result:
Promise.race([
new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3
]).then((value) => console.log(value));
// Output: 3 (after 1 second - fastest wins)
Promise.any()
Waits for the FIRST fulfilled promise and returns it. If all promises are rejected, returns a promise with AggregateError:
Promise.any([
new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 1000)),
new Promise((resolve, reject) => setTimeout(() => resolve(1), 2000)),
new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).then((value) => console.log(value));
// Output: 1 (first successful resolution)
Promise Method Comparison
| Method | Behavior | Result |
|---|---|---|
Promise.all() | Waits for ALL to resolve | Array of all results OR first rejection |
Promise.race() | Waits for FIRST to settle | First settled result (resolve OR reject) |
Promise.any() | Waits for FIRST to resolve | First resolved result OR AggregateError |
Common Use Cases
Sequential vs Parallel Execution
// Sequential (slower)
async function sequential() {
const result1 = await promise1(); // Wait for first
const result2 = await promise2(); // Then wait for second
return [result1, result2];
}
// Parallel (faster)
async function parallel() {
const [result1, result2] = await Promise.all([
promise1(), // Start both simultaneously
promise2()
]);
return [result1, result2];
}
Error Handling Best Practices
async function handleErrors() {
try {
const results = await Promise.all([
fetchUserData(),
fetchUserPosts(),
fetchUserFriends()
]);
return results;
} catch (error) {
console.error('One or more operations failed:', error);
throw error;
}
}
Key Takeaways
- Promise.all(): Use when you need ALL operations to succeed
- Promise.race(): Use for timeout scenarios or when you want the fastest response
- Promise.any(): Use when you need at least ONE operation to succeed
- Always handle errors: Use
.catch()or try-catch with async/await - Parallel > Sequential: Use Promise.all() for independent operations
Understanding Promises is essential for modern JavaScript development and forms the foundation for async/await syntax.