JavaScript Promise Methods Reference
Complete guide to JavaScript Promise methods — then, catch, finally, and all static methods with practical examples
Introduction
Promises are JavaScript's built-in solution for handling asynchronous operations. Understanding all Promise methods is essential for writing clean, maintainable async code. This reference covers every Promise method with practical examples.
Instance Methods
then()
Purpose: Handles a fulfilled (resolved) promise.
Signature: promise.then(onFulfilled, onRejected)
Parameters:
onFulfilled(optional): Function called when the promise is fulfilledonRejected(optional): Function called when the promise is rejected
Returns: A new Promise that resolves with the return value of the callback
// Basic usage
const promise = Promise.resolve('Hello');
promise.then((value) => {
console.log(value); // 'Hello'
return value.toUpperCase();
}).then((result) => {
console.log(result); // 'HELLO'
});
// Chaining multiple then() calls
fetch('/api/user')
.then(response => response.json())
.then(user => user.name)
.then(name => console.log(name));
Important Notes:
then()always returns a new Promise- If
onFulfilledreturns a value, the new Promise resolves with that value - If
onFulfilledthrows an error, the new Promise rejects with that error - You can omit
onFulfilledto skip to the next handler
// onFulfilled can be omitted
promise.then(null, (error) => {
console.error(error);
});
// Better: use catch() for errors
promise.catch((error) => {
console.error(error);
});
catch()
Purpose: Handles a rejected promise. Syntactic sugar for then(null, onRejected).
Signature: promise.catch(onRejected)
Parameters:
onRejected: Function called when the promise is rejected
Returns: A new Promise that resolves with the return value of the callback
// Basic error handling
fetch('/api/user')
.then(response => response.json())
.catch(error => {
console.error('Failed to fetch user:', error);
return { name: 'Guest' }; // Provide fallback value
})
.then(user => console.log(user.name));
// Catching specific errors
fetch('/api/user')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
})
.catch(error => {
if (error.message.includes('HTTP 404')) {
console.log('User not found');
} else if (error.message.includes('HTTP 500')) {
console.log('Server error');
} else {
console.error('Unknown error:', error);
}
});
Important Notes:
catch()is equivalent tothen(undefined, onRejected)- Errors in
then()handlers are caught by subsequentcatch() - A
catch()handler can return a value to recover from errors - To re-throw an error, use
throw errorin the catch block
// Error recovery pattern
apiCall()
.catch(error => {
console.error('Primary failed, trying fallback');
return fallbackCall(); // Returns a value or Promise
})
.then(result => {
// Works with either primary or fallback result
});
// Re-throwing errors
apiCall()
.catch(error => {
console.error('Logging error:', error);
throw error; // Re-throw for upstream handler
})
.catch(error => {
// Handle the re-thrown error
});
finally()
Purpose: Called when a promise is settled (either fulfilled or rejected).
Signature: promise.catch(onFinally)
Parameters:
onFinally: Function called when the promise settles (no arguments passed)
Returns: A new Promise with the same result as the original promise
// Loading state management
let isLoading = false;
fetch('/api/data')
.then(data => {
// Handle success
})
.catch(error => {
// Handle error
})
.finally(() => {
isLoading = false; // Always executed
console.log('Request completed');
});
// Cleanup operations
let connection;
connectToDatabase()
.then(conn => {
connection = conn;
return connection.query('SELECT * FROM users');
})
.then(results => {
// Process results
})
.catch(error => {
// Handle errors
})
.finally(() => {
if (connection) {
connection.close(); // Always close connection
}
});
Important Notes:
onFinallyreceives no arguments (unlikethen/catch)- The Promise chain continues with the original result after
finally() - If
onFinallythrows an error, the Promise rejects with that error - Perfect for cleanup, loading indicators, and resource management
Static Methods
Promise.resolve()
Purpose: Creates a Promise that resolves with a given value.
Signature: Promise.resolve(value)
Returns: A Promise that resolves with the provided value
// Convert a value to a Promise
const promise = Promise.resolve('Hello');
promise.then(console.log); // 'Hello'
// Convert thenable to Promise
const thenable = {
then(resolve) {
resolve('Resolved!');
}
};
Promise.resolve(thenable).then(console.log); // 'Resolved!'
// If already a Promise, returns the same Promise
const existingPromise = Promise.resolve('test');
Promise.resolve(existingPromise) === existingPromise; // true
// Practical usage: normalize sync/async functions
const maybeAsync = (value, isAsync) => {
if (isAsync) {
return fetch('/api/data').then(res => res.json());
}
return Promise.resolve(value); // Wrap sync value
};
Promise.reject()
Purpose: Creates a Promise that rejects with a given reason.
Signature: Promise.reject(reason)
Returns: A Promise that rejects with the provided reason
// Create a rejected Promise
const error = new Error('Something failed');
Promise.reject(error).catch(console.error);
// Practical usage: fail fast in conditional logic
const getUser = (id) => {
if (!id) {
return Promise.reject(new Error('ID is required'));
}
return fetch(`/api/users/${id}`).then(res => res.json());
};
// Reject with custom error types
Promise.reject(new TypeError('Invalid type'))
.catch(error => {
if (error instanceof TypeError) {
// Handle type error
}
});
Promise.all()
Purpose: Waits for all Promises to resolve, or rejects if any Promise rejects.
Signature: Promise.all(iterable)
Returns: A Promise that resolves with an array of all results, or rejects with the first error
// Wait for multiple promises
const [user, posts, comments] = await Promise.all([
fetch('/api/user').then(res => res.json()),
fetch('/api/posts').then(res => res.json()),
fetch('/api/comments').then(res => res.json())
]);
// All must succeed - if one fails, all fail
Promise.all([
Promise.resolve(1),
Promise.reject(new Error('Failed')),
Promise.resolve(3)
]).catch(error => {
console.error(error.message); // 'Failed'
});
// Practical usage: parallel API calls
const fetchAllData = async () => {
try {
const [users, products, orders] = await Promise.all([
fetch('/api/users').then(r => r.json()),
fetch('/api/products').then(r => r.json()),
fetch('/api/orders').then(r => r.json())
]);
return { users, products, orders };
} catch (error) {
console.error('Failed to load dashboard:', error);
throw error;
}
};
Important Notes:
- All Promises must resolve for
Promise.all()to resolve - If any Promise rejects,
Promise.all()immediately rejects - Results are returned in the same order as the input array
- Great for parallel operations where all must succeed
Promise.allSettled()
Purpose: Waits for all Promises to settle (resolve or reject).
Signature: Promise.allSettled(iterable)
Returns: A Promise that resolves with an array of result objects with { status, value/reason }
// Wait for all promises regardless of outcome
const results = await Promise.allSettled([
Promise.resolve('Success'),
Promise.reject(new Error('Failed')),
Promise.resolve('Also success')
]);
console.log(results);
// [
// { status: 'fulfilled', value: 'Success' },
// { status: 'rejected', reason: Error: Failed },
// { status: 'fulfilled', value: 'Also success' }
// ]
// Practical usage: batch operations with partial failures
const emailResults = await Promise.allSettled(
emails.map(email => sendEmail(email))
);
const successful = emailResults.filter(r => r.status === 'fulfilled');
const failed = emailResults.filter(r => r.status === 'rejected');
console.log(`Sent ${successful.length}, Failed ${failed.length}`);
Important Notes:
- Never rejects - always resolves with status array
- Each result has
status('fulfilled' or 'rejected') - Fulfilled results have
value, rejected havereason - Perfect for batch operations where partial success is acceptable
Promise.race()
Purpose: Returns the first Promise that settles (resolves or rejects).
Signature: Promise.race(iterable)
Returns: A Promise that settles with the first Promise's result
// Race between multiple promises
const winner = await Promise.race([
fetch('/api/primary'),
fetch('/api/backup'),
fetch('/api/fallback')
]);
// Timeout pattern
const withTimeout = (promise, ms) => {
const timeout = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Timeout')), ms);
});
return Promise.race([promise, timeout]);
};
// Usage
try {
const data = await withTimeout(
fetch('/api/slow-endpoint').then(r => r.json()),
5000 // 5 second timeout
);
} catch (error) {
if (error.message === 'Timeout') {
console.error('Request took too long');
}
}
Important Notes:
- Returns immediately when first Promise settles
- If first is fulfilled,
race()fulfills; if rejected,race()rejects - Other Promises continue running (not cancelled)
- Useful for timeouts and fallback strategies
Promise.any()
Purpose: Returns the first Promise that fulfills, or rejects if all Promises reject.
Signature: Promise.any(iterable)
Returns: A Promise that fulfills with the first successful result, or rejects with AggregateError
// Get first successful result
const result = await Promise.any([
fetch('/api/primary').then(r => r.json()),
fetch('/api/backup').then(r => r.json()),
fetch('/api/fallback').then(r => r.json())
]);
// If all fail, get AggregateError
try {
const result = await Promise.any([
Promise.reject(new Error('Failed 1')),
Promise.reject(new Error('Failed 2'))
]);
} catch (error) {
if (error instanceof AggregateError) {
console.log('All promises rejected:', error.errors);
// error.errors is an array of all rejection reasons
}
}
// Practical usage: try multiple CDNs
const loadFromFastestCDN = async () => {
try {
const response = await Promise.any([
fetch('https://cdn1.example.com/data.json'),
fetch('https://cdn2.example.com/data.json'),
fetch('https://cdn3.example.com/data.json')
]);
return await response.json();
} catch (error) {
throw new Error('All CDNs failed');
}
};
Important Notes:
- Only fulfills on success, ignores rejections
- Rejects with
AggregateErroronly if ALL Promises reject AggregateError.errorscontains all rejection reasons- ES2021 feature - check browser support
Error Handling Best Practices
Always Handle Errors
// ❌ Unhandled promise rejection
fetch('/api/data').then(data => process(data));
// ✅ Always add catch
fetch('/api/data')
.then(data => process(data))
.catch(error => console.error(error));
// ✅ Or use async/await with try-catch
try {
const data = await fetch('/api/data').then(r => r.json());
process(data);
} catch (error) {
console.error(error);
}
Chain Errors Properly
// ❌ Error can be lost
promise
.then(handler)
.catch(logError)
.then(continueProcessing); // Runs even if error occurred
// ✅ Re-throw or handle
promise
.then(handler)
.catch(error => {
logError(error);
throw error; // Re-throw to stop chain
});
Use Specific Error Types
class APIError extends Error {
constructor(status, message) {
super(message);
this.status = status;
this.name = 'APIError';
}
}
fetch('/api/data')
.then(response => {
if (!response.ok) {
throw new APIError(response.status, 'Request failed');
}
return response.json();
})
.catch(error => {
if (error instanceof APIError) {
handleAPIError(error.status);
} else {
handleGenericError(error);
}
});
Summary Table
| Method | Type | Purpose | Returns |
|---|---|---|---|
then() | Instance | Handle fulfillment | New Promise |
catch() | Instance | Handle rejection | New Promise |
finally() | Instance | Cleanup on settle | New Promise |
resolve() | Static | Create resolved Promise | Promise |
reject() | Static | Create rejected Promise | Promise |
all() | Static | Wait for all (fail-fast) | Promise array |
allSettled() | Static | Wait for all (no fail) | Status array |
race() | Static | First to settle | First result |
any() | Static | First to fulfill | First success |
Conclusion
Mastering Promise methods gives you complete control over asynchronous operations. Use:
then()/catch()/finally()for handling individual PromisesPromise.all()when all operations must succeedPromise.allSettled()for batch operations with partial failuresPromise.race()for timeouts and fallbacksPromise.any()when you need the first successful result
Combine these methods to build robust, error-resistant async code.
#javascript #async #promises #reference #web-development