Leaderboard
Javascript Jul 1, 2026
Javascript Promise All Fail Fast Behavior

JavaScript Promise.all — What Happens on Single Rejection?

This is a daily Javascript challenge from the CodeShot archive. Practice your knowledge of Promise All Fail Fast Behavior and improve your technical interview readiness.

Promise.all([
  Promise.resolve(1),
  Promise.reject("error"),
  Promise.resolve(3)
]).then(console.log).catch(console.error)
A Logs [1, "error", 3]
B Immediately rejects with "error" — the other promises are ignored
C Logs [1, undefined, 3]
D Waits for all then logs the results

Detailed Explanation

Why This Question Matters

If you've spent any time working with asynchronous JavaScript, you've used Promise.all(). It seems straightforward: throw a bunch of promises into an array, and when they're all done, you get the results.

But there's a specific behavior in Promise.all() that trips up a lot of developers—especially during technical interviews or when debugging a production crash. The confusion usually stems from a misunderstanding of "fail-fast" behavior. People often assume Promise.all() waits for every single promise to settle before deciding what to do. It doesn't.

Understanding exactly how it handles a single rejection is the difference between a robust API integration and a codebase where errors silently vanish or crash your app unexpectedly.

Understanding the Code

Let's look at the snippet:

Promise.all([
  Promise.resolve(1),
  Promise.reject("error"),
  Promise.resolve(3)
]).then(console.log).catch(console.error)

On the surface, we have three promises. Two are successful, and one is a rejection.

Internally, Promise.all() acts as a coordinator. It monitors the state of every promise in the provided array. As soon as one of those promises changes state to "rejected," the coordinator stops waiting. It doesn't matter if the other promises are still pending or if they eventually resolve successfully.

The moment Promise.reject("error") triggers, the entire Promise.all() call rejects immediately. It bypasses the .then() block entirely and jumps straight to the .catch() block.

Finding the Correct Answer

In this challenge, the correct answer is Option B, which would be the output: error.

Why not [1, "error", 3]? Because Promise.all() is all-or-nothing. It doesn't return a partial list of results. If one fails, the whole operation is considered a failure.

Why not wait for the third promise to resolve? Because of the fail-fast mechanism. The engine doesn't waste time waiting for Promise.resolve(3) to finish if it already knows the final result of the Promise.all() call will be a rejection.

The flow looks like this:
1. Promise.all starts.
2. It sees Promise.resolve(1) (Success).
3. It sees Promise.reject("error") (Failure!).
4. Immediate trigger: The main promise rejects with the value "error".
5. The .catch(console.error) executes.

Common Mistakes Developers Make

The biggest mistake is assuming Promise.all() is a "collect all" tool. Developers often think it will gather all the errors and successes and give them a report at the end.

Another common trap is forgetting that the other promises still run. Just because Promise.all() rejected doesn't mean the other async operations were cancelled. If you triggered three API calls and the second one failed, the first and third calls are still hitting your server; you're just ignoring their results.

I've also seen developers try to "fix" this by wrapping every single promise in its own .catch() inside the array. While that works, it's often a sign that they should be using a different method entirely.

Real-World Usage

In a real production environment, Promise.all() is great when your tasks are interdependent.

Imagine you're building a dashboard. You need the User Profile, the User Settings, and the User Permissions before you can render the page. If the Permissions call fails, the page is broken anyway. In this case, fail-fast is exactly what you want. You catch the error and show a "Something went wrong" page.

However, if the tasks are independent, Promise.all() is a dangerous choice.

Suppose you're fetching data from five different third-party widgets. If one widget's API is down, do you really want to hide the other four working widgets? Probably not. This is where Promise.allSettled() comes in.

Promise.allSettled() waits for everything to finish regardless of the outcome and returns an array of objects describing the state of each promise. If you need a "best effort" approach, use allSettled. If you need "perfect or nothing," use all.

Key Takeaways

- Promise.all() is fail-fast. One rejection kills the whole operation.
- It does not return partial results; it returns either the full array of successes or the first error it encounters.
- Rejection happens immediately upon the first failure, regardless of the order of the promises in the array.
- Other promises in the array continue to execute in the background—they aren't magically cancelled.
- Use Promise.all() for interdependent tasks and Promise.allSettled() for independent ones.

Why this matters

Understanding Promise All Fail Fast Behavior is crucial for passing technical interviews. In real-world applications, this concept often leads to subtle bugs if not handled correctly. For more details, you can always refer to the official MDN Documentation.

📝
Reviewed by CodeShot Editorial
Every challenge is code-reviewed by senior developers to ensure accuracy and real-world relevance. Learn more.

Ready for your shot?

Join thousands of developers solving one logic puzzle every morning.

Solve Today's Challenge →