JavaScript > Asynchronous JavaScript > Promises > Chaining promises
Promise Chaining in JavaScript
This example demonstrates how to chain promises in JavaScript to execute asynchronous operations sequentially. Promise chaining allows you to manage asynchronous code in a more readable and maintainable way by linking asynchronous tasks together.
Basic Promise Chaining
This code demonstrates a basic promise chain. Each .then()
block receives the result of the previous promise and returns a new promise. The next .then()
in the chain waits for this new promise to resolve before executing. The .catch()
block handles any errors that occur in the chain.
// Function that returns a promise which resolves after a delay
function delayedResolve(value, delay) {
return new Promise(resolve => {
setTimeout(() => {
resolve(value);
}, delay);
});
}
// Chain promises together
delayedResolve('First', 1000)
.then(result => {
console.log(result); // Output: First
return delayedResolve('Second', 500);
})
.then(result => {
console.log(result); // Output: Second
return delayedResolve('Third', 250);
})
.then(result => {
console.log(result); // Output: Third
console.log('All done!');
})
.catch(error => {
console.error('An error occurred:', error);
});
Concepts Behind Promise Chaining
Promise chaining works because the .then()
method returns a new promise. If the function passed to .then()
returns a value, the promise returned by .then()
will resolve with that value. If the function passed to .then()
returns a promise, the promise returned by .then()
will 'adopt' the state of that returned promise. This means the promise returned by .then()
will resolve or reject with the same value or reason as the promise returned by the function. This 'adoption' allows you to create a chain of dependent asynchronous operations.
Real-Life Use Case
Imagine you need to fetch data from an API, then process that data, and finally update the UI. Promise chaining is perfect for this scenario. You can chain these three operations together, ensuring they execute in the correct order. For example, first authenticate with API, then use the token received to get data from an endpoint, and finally display the received data on user interface.
Best Practices
.catch()
block at the end of your promise chain to handle any errors that might occur.async/await
for more complex asynchronous flows..then()
handler returns a value or a promise. Returning undefined
can lead to unexpected behavior.
Interview Tip
Be prepared to explain how promise chaining works under the hood. Understand that .then()
always returns a promise, and the state of that promise depends on the value or promise returned by the .then()
handler. Also understand the importance of error handling with .catch().
When to Use Them
Use promise chaining when you need to execute a series of asynchronous operations in a specific order, where each operation depends on the result of the previous one. Promise chaining is very efficient in cases like authentication, fetching, and processing of data.
Memory Footprint
Promise chains are generally memory-efficient, as each promise only exists for the duration of its execution. Once a promise resolves or rejects, its associated resources can be garbage collected. However, very long chains can potentially consume more memory, so consider refactoring into smaller, more manageable chunks if necessary. Use `async/await` which generally compiles to a more performant promise execution.
Alternatives
The main alternative to promise chaining is async/await
, which provides a more synchronous-looking syntax for working with promises. async/await
is often preferred for its improved readability, especially for complex asynchronous workflows. Another option is using Reactive Extensions (RxJS) which offers a more powerful and flexible approach to handling asynchronous data streams, but has a higher learning curve.
Pros
.catch()
block.
Cons
FAQ
-
What happens if an error occurs in a promise chain?
If an error occurs (either a synchronous error or a rejected promise) in a.then()
handler, the promise chain will be short-circuited. The error will propagate down the chain until it reaches a.catch()
handler, which will then handle the error. -
Can I have multiple
.catch()
handlers in a promise chain?
Yes, but generally you only need one.catch()
handler at the end of the chain. Adding multiple.catch()
handlers can make the code harder to understand. A.catch()
handler will only be executed if an error occurs before it in the chain. If the error is handled, the promise returned by .catch() will resolve, and the chain continues (if there's something after the .catch() ). -
How does
async/await
relate to promise chaining?
async/await
is syntactic sugar over promises. It allows you to write asynchronous code that looks and behaves a bit more like synchronous code. When you useawait
, you are essentially pausing the execution of theasync
function until the promise that you are awaiting resolves. It makes chaining easier to read.