1. Introduction to Promises
A Promise in JavaScript is an object representing the eventual completion (or failure) of an asynchronous operation and its resulting value.
Promises have three states:
Pending: Initial state, neither fulfilled nor rejected.
Fulfilled: The operation completed successfully.
Rejected: The operation failed.
2. Promise APIs
a. Promise.all()
Purpose: Takes an iterable of promises and returns a single promise that resolves when all of the promises in the iterable have resolved, or rejects if any of the promises reject.
Use Case: Useful when you want to wait for multiple asynchronous operations to complete successfully.
Example:
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.resolve(3);
Promise.all([p1, p2, p3])
.then(values => console.log(values)) // [1, 2, 3]
.catch(error => console.error(error));
Behavior:
If all promises resolve, Promise.all resolves with an array of results.
If any promise rejects, Promise.all immediately rejects with the reason of the first rejected promise.
b. Promise.allSettled()
Purpose: Takes an iterable of promises and returns a promise that resolves after all of the promises have either resolved or rejected.
Use Case: Useful when you want to know the outcome of all promises, regardless of whether they succeeded or failed.
Example:
const p1 = Promise.resolve(1);
const p2 = Promise.reject("Error");
const p3 = Promise.resolve(3);
Promise.allSettled([p1, p2, p3])
.then(results => console.log(results));
/* Output:
[
{ status: 'fulfilled', value: 1 },
{ status: 'rejected', reason: 'Error' },
{ status: 'fulfilled', value: 3 }
]
*/
Behavior:
Returns an array of objects, each describing the outcome of each promise.
c. Promise.race()
Purpose: Takes an iterable of promises and returns a promise that resolves or rejects as soon as one of the promises in the iterable resolves or rejects.
Use Case: Useful when you want to respond to the first completed promise (either resolved or rejected).
Example:
const p1 = new Promise((resolve) => setTimeout(resolve, 500, "First"));
const p2 = new Promise((resolve) => setTimeout(resolve, 100, "Second"));
Promise.race([p1, p2])
.then(result => console.log(result)); // "Second"
Behavior:
The result is based on the first promise to settle (either resolve or reject).
d. Promise.any()
Purpose: Takes an iterable of promises and returns a promise that resolves as soon as any of the promises in the iterable resolves. If all promises reject, it rejects with an AggregateError.
Use Case: Useful when you want the first successful result and can handle cases where all promises might fail.
Example:
const p1 = Promise.reject("Error 1");
const p2 = Promise.resolve("Success");
const p3 = Promise.reject("Error 2");
Promise.any([p1, p2, p3])
.then(result => console.log(result)) // "Success"
.catch(error => console.error(error));
Behavior:
Resolves with the value of the first resolved promise.
Rejects with an AggregateError if all promises reject.
4. Interview Questions
a. What is the difference between Promise.all() and Promise.allSettled()?
Promise.all() rejects immediately if any promise in the iterable rejects, while Promise.allSettled() waits for all promises to settle (either resolve or reject) and returns their outcomes.
b. When would you use Promise.race()?
Promise.race() is useful when we want to respond to the first completed asynchronous operation, such as implementing a timeout or prioritizing the fastest response.
c. What happens if all promises passed to Promise.any() reject?
If all promises reject, Promise.any() rejects with an AggregateError containing the reasons for all rejections.
d. Can you polyfill Promise.any()?
Yes, we can create a polyfill for Promise.any() using Promise.allSettled() and custom logic to handle the first resolved promise.
Key Points:
🔑 Promise.all handles multiple promises simultaneously, returning an array of results when all promises are fulfilled, and throwing an error if any promise fails.
🔑 If any promise in Promise.all fails, the entire operation fails, and an error is thrown immediately without waiting for other promises.
🔑 Promise.allSettled waits for all promises to settle (whether fulfilled or rejected) before returning an array of results or errors, making it suitable for scenarios where partial failures are acceptable.
🔑 Promise.race returns the result of the first settled promise, whether it's success or failure, making it ideal for scenarios where the fastest response is required.
🔑 Promise.any is similar to Promise.race but waits for the first successful promise rather than the first settled one, making it suitable for scenarios where success is prioritized over speed.
🔍 Promise.any returns the result of the first successful promise and ignores subsequent failures, waiting for success.
🏁 Promise.any collects errors if all promises fail and returns an aggregated error array.
🔄 Promise.all returns an array of all results when all promises succeed, waiting for all to finish.
🛠 Promise.allSettled waits for all promises to settle (succeed or fail) before returning results, ensuring all promises are accounted for.
🏎 Promise.race returns the result of the first settled promise, whether success or failure, racing to return the fastest result.
📝 Promise status can be checked for rejection along with the reason for rejection, providing clarity in handling errors.
🚀 Promise.race returns the result of the first settled promise, whether it's a success or failure, regardless of the order in which promises are fulfilled.
💡 Explaining concepts in interviews requires not only understanding but also the ability to articulate ideas clearly, which is often a stumbling block for many candidates.
🔑 Promise.race resolves to the value/error of the first settled promise, regardless of success or failure, emphasizing the importance of understanding terminology in the Promise world.
📚 Familiarity with Promise terminology like "settled," "resolved," "rejected," "fulfilled," and "rejected" is crucial for effectively working with Promise APIs.
📝 Promise.any waits for the first settled promise, and if it's a success, returns the result, ignoring subsequent rejections until a success occurs.
📊 When all promises fail with Promise.any, it results in an "aggregate error," which consolidates all the errors encountered during execution.
🛠 Handling aggregate errors in Promise.any involves accessing the errors in an array format, allowing for comprehensive error management and analysis.

Comments
Post a Comment