JavaScript: Promise Chaining

Promise chaining is a technique where each promise returns another promise, allowing them to be linked together. This approach is very useful when you need to perform multiple asynchronous operations back to back, where each subsequent operation starts when the previous one finishes.

To find out more about the nature of promises in JavaScript, see JavaScript: Promises.

Basic Promise Chaining

Consider the scenario where you need to query a database, then use the result of that query to make another query, and finally render the result on the screen. Here’s how you can implement this using promise chaining:

function queryDatabase(query) { return new Promise((resolve, reject) => { // Database querying logic setTimeout(() => { const result = 'data from ' + query; resolve(result); }, 1000); // simulate async delay }); } queryDatabase('Select * FROM users') .then(result => { console.log('Query result:', result); return queryDatabase('Select * FROM posts WHERE user_id = 1'); }) .then(result => { console.log('Posts:', result); }) .catch(error => { console.error('Error:', error); });

Error Handling in Chains

Proper error handling within promise chains is crucial to prevent crashes and unintended behavior. A single .catch() at the end of the chain can handle any error that occurs at any point in the promise chain.

function queryDatabase(query) { return new Promise((resolve, reject) => { // Database querying logic setTimeout(() => { const result = 'data from ' + query; resolve(result); }, 1000); // simulate async delay }); } queryDatabase('Select * FROM users') .then(result => { throw new Error("error here!") }) .catch(error => { console.log('Error:', error); });

Advanced Techniques in Promise Chaining

Besides basic chaining, you can enhance your promise-based workflows with these advanced techniques:

Returning Values

Each .then() can return a value which will be wrapped in a new promise and passed to the next .then() in the chain.

new Promise((resolve, reject) => { setTimeout(() => resolve(1), 1000); }) .then(result => { console.log(result); // 1 return result * 2; }) .then(result => { console.log(result); // 2 return result * 3; }) .then(result => { console.log(result); // 6 return result * 4; });

Promise.all

When you have multiple promises and you need to wait for all of them to complete, Promise.all is incredibly useful. It takes an array of promises and returns a new promise that resolves when all of the input promises have resolved.

const promise1 = Promise.resolve(3); const promise2 = 42; const promise3 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'foo'); }); Promise.all([promise1, promise2, promise3]).then(values => { console.log(values); // [3, 42, 'foo'] });

Conclusion

JavaScript promises and their chaining are indispensable in modern web development, especially when dealing with multiple asynchronous events or actions that need to occur in a specific sequence. By mastering promises, you can write cleaner, more efficient JavaScript code and improve your web applications' performance and reliability.

Practice Your Knowledge

What is the purpose of Promise Chaining in JavaScript?

Quiz Time: Test Your Skills!

Ready to challenge what you've learned? Dive into our interactive quizzes for a deeper understanding and a fun way to reinforce your knowledge.

Do you find this helpful?