JavaScript Promise API

In JavaScript, mastering promises is crucial for developing responsive, scalable, and maintainable applications. For an introduction to promises, see our previous pages like JavaScript: Promises. This article delves deep into the nuanced aspects of JavaScript Promises, specifically focusing on Promise.all, Promise.allSettled, Promise.race, and the implementation of polyfills for these methods. By enhancing your understanding and ability to implement these advanced techniques, you will significantly improve the efficiency and reliability of your JavaScript code.

Utilizing Promise.all for Concurrent Tasks

Promise.all is an essential method for handling multiple promises concurrently. When you need to perform several asynchronous operations and only proceed once all of them have successfully completed, Promise.all is the tool you need.

How to Implement Promise.all

Below is an example demonstrating how to use Promise.all to handle multiple API requests simultaneously:

const getFirstTodo = fetch('https://jsonplaceholder.typicode.com/todos/1'); const getSecondTodo = fetch('https://jsonplaceholder.typicode.com/todos/2'); Promise.all([getFirstTodo, getSecondTodo]) .then(responses => Promise.all(responses.map(res => res.json()))) .then(data => console.log(data)) .catch(error => console.error("Error in executing Promise.all", error));

In this example, Promise.all takes an array of promises, and it resolves to an array of the results from these promises. If any promise fails, Promise.all rejects with the reason of the first promise that rejected.

Mastering Promise.allSettled

Unlike Promise.all, the Promise.allSettled method returns a promise that resolves after all the given promises have either resolved or rejected, with an array of objects that each describe the outcome of each promise.

Example of Promise.allSettled

Here's how you can use Promise.allSettled:

const getFirstTodo = fetch('https://jsonplaceholder.typicode.com/todos/1'); const getSecondTodo = fetch('https://jsonplaceholder.typicode.com/todos/2') .then(() => { throw new Error('second todo failed somehow!') }); Promise.allSettled([getFirstTodo, getSecondTodo]) .then(results => results.forEach((result) => console.log(result.status))) .catch(error => console.error("Error in executing Promise.allSettled", error));

This method is particularly useful when you need to ensure that all promises proceed to completion regardless of whether they are fulfilled or rejected.

Implementing Promise.race

Promise.race is another powerful tool that allows handling multiple promises by resolving or rejecting as soon as one of the promises in the iterable resolves or rejects.

How to Use Promise.race

Below is a practical application of Promise.race:

const getFirstTodo = fetch('https://jsonplaceholder.typicode.com/todos/1'); const getSecondTodo = fetch('https://jsonplaceholder.typicode.com/todos/2'); Promise.race([getFirstTodo, getSecondTodo]) .then((res) => res.json()) .then((res) => { console.log(res.id); // Run multiple times, get different answers }) .catch(error => console.error("Error in executing Promise.race", error));

This method is ideal for scenarios where you need the fastest result among multiple asynchronous operations.

Creating a Polyfill for Promise.allSettled

Not all environments support Promise.allSettled natively. Therefore, implementing a polyfill can ensure compatibility across different JavaScript environments.

Polyfill for Promise.allSettled

Here’s how you can create a simple polyfill:

Promise.allSettled = promises => { console.log("Our own custom allSettled is called!"); return Promise.all(promises.map(p => Promise.resolve(p).then( value => ({ status: 'fulfilled', value }), reason => ({ status: 'rejected', reason }) ))) }; const firstPromise = new Promise((res) => res("success")); const secondPromise = new Promise((res) => rej("failure")); Promise.allSettled([firstPromise, secondPromise]) .then(console.log);

This polyfill provides a basic functionality where each promise is individually handled and resolved to its respective outcome, ensuring the allSettled behavior is mimicked effectively.

By integrating these advanced promise techniques and understanding the underlying mechanics of polyfills, you can elevate your JavaScript code to new heights. These methods not only enhance code reliability but also offer refined control over asynchronous operations, paving the way for more robust web applications.

Practice Your Knowledge

Which of the following statements are true about Promises in JavaScript according to the information provided on the website?

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?