Master all four JavaScript Promise static methods with real-world examples, comparison diagrams, error handling patterns, and interview questions. Learn when to use Promise.all vs allSettled vs race vs any with detailed explanations.
Introduction
In JavaScript, when you need to manage multiple asynchronous operations simultaneously — like calling 3 APIs in parallel, or picking the fastest response — you use Promise static methods.
There are 4 methods:
| Method | One-line Summary |
|---|
Promise.all() | Resolves when all resolve; rejects immediately if any one fails |
Promise.allSettled() | Waits for all to complete, whether resolved or rejected — never rejects |
Promise.race() | Returns the result of whichever settles first (resolve or reject) |
Promise.any() | Returns the result of whichever resolves first, rejects only if all fail |
Understanding these methods is essential because in real-world applications you need to:
- Call multiple APIs in parallel to improve performance
- Implement timeouts
- Handle partial failures gracefully
- Use the fastest available response
Promise.all() — All Must Succeed
Promise.all() takes an array of promises and returns a single promise that resolves when all promises resolve. If any single promise rejects, the entire result immediately rejects with that error.
Key characteristics:
- Resolves with an array of all values (same order as input)
- Rejects with the first rejection reason (other results discarded)
- All promises run in parallel — not sequentially
Example 1: All Promises Succeed
const p1 = Promise.resolve("User Data");
const p2 = Promise.resolve("Posts Data");
const p3 = Promise.resolve("Comments Data");
Promise.all([p1, p2, p3])
.then(results => {
console.log("All resolved!");
console.log("Results:", results);
console.log("Count:", results.length);
});
All resolved!
Results: [ 'User Data', 'Posts Data', 'Comments Data' ]
Count: 3
Example 2: One Promise Fails (Fail-Fast)
const p1 = Promise.resolve("Success 1");
const p2 = Promise.reject(new Error("Network Error"));
const p3 = Promise.resolve("Success 3");
Promise.all([p1, p2, p3])
.then(results => {
console.log("This never runs:", results);
})
.catch(error => {
console.log("Promise.all rejected!");
console.log("Error:", error.message);
console.log("Other results are LOST");
});
Promise.all rejected!
Error: Network Error
Other results are LOST
Example 3: Simulating Parallel API Calls
function fakeAPI(name, delay, shouldFail = false) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldFail) reject(new Error(`${name} failed`));
else resolve({ api: name, data: `${name} response`, time: delay });
}, delay);
});
}
async function loadDashboard() {
console.log("Loading dashboard (parallel)...");
const start = Date.now();
try {
const [users, posts, stats] = await Promise.all([
fakeAPI("Users", 300),
fakeAPI("Posts", 500),
fakeAPI("Stats", 200)
]);
const elapsed = Date.now() - start;
console.log(`✅ All loaded in ~${elapsed}ms (parallel)`);
console.log("Users:", users.data);
console.log("Posts:", posts.data);
console.log("Stats:", stats.data);
} catch (error) {
console.log("❌ Dashboard failed:", error.message);
}
}
loadDashboard();
Loading dashboard (parallel)...
✅ All loaded in ~500ms (parallel)
Users: Users response
Posts: Posts response
Stats: Stats response
Note: Sequential loading would take 300+500+200 = 1000ms. Promise.all takes only ~500ms (slowest request ka time).
Promise.allSettled() — Wait for All, Never Reject
Promise.allSettled() waits for all promises to settle — whether they resolve or reject. This method never rejects. The result contains each promise's status ("fulfilled" or "rejected") along with its value or reason.
Key characteristics:
- Always resolves — never rejects
- Returns array of
{ status, value } or { status, reason } objects - Perfect for "best effort" scenarios where partial success is acceptable
Example 4: Mixed Results with allSettled
const promises = [
Promise.resolve(42),
Promise.reject(new Error("DB Connection Lost")),
Promise.resolve("Hello World"),
Promise.reject(new Error("Timeout")),
Promise.resolve([1, 2, 3])
];
Promise.allSettled(promises).then(results => {
console.log("All settled! Never rejects.\n");
results.forEach((result, index) => {
if (result.status === "fulfilled") {
console.log(` #${index}: ✅ fulfilled → ${JSON.stringify(result.value)}`);
} else {
console.log(` #${index}: ❌ rejected → ${result.reason.message}`);
}
});
const fulfilled = results.filter(r => r.status === "fulfilled");
const rejected = results.filter(r => r.status === "rejected");
console.log(`\nSummary: ${fulfilled.length} succeeded, ${rejected.length} failed`);
});
All settled! Never rejects.
#0: ✅ fulfilled → 42
#1: ❌ rejected → DB Connection Lost
#2: ✅ fulfilled → "Hello World"
#3: ❌ rejected → Timeout
#4: ✅ fulfilled → [1,2,3]
Summary: 3 succeeded, 2 failed
Example 5: Resilient Multi-Source Data Loading
function fakeAPI(name, delay, shouldFail = false) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldFail) reject(new Error(`${name}: Service Unavailable`));
else resolve({ source: name, records: Math.floor(Math.random() * 100) });
}, delay);
});
}
async function loadFromMultipleSources() {
const results = await Promise.allSettled([
fakeAPI("Primary DB", 200),
fakeAPI("Cache Server", 100, true), // This will fail
fakeAPI("Backup DB", 300),
fakeAPI("CDN", 150, true) // This will fail too
]);
const successData = [];
const errors = [];
results.forEach((result, i) => {
if (result.status === "fulfilled") {
successData.push(result.value);
} else {
errors.push(result.reason.message);
}
});
console.log("✅ Successful sources:");
successData.forEach(d => console.log(` ${d.source}: ${d.records} records`));
console.log("\n❌ Failed sources:");
errors.forEach(e => console.log(` ${e}`));
console.log(`\n📊 Loaded from ${successData.length}/4 sources`);
}
loadFromMultipleSources();
✅ Successful sources:
Primary DB: 47 records
Backup DB: 82 records
❌ Failed sources:
Cache Server: Service Unavailable
CDN: Service Unavailable
📊 Loaded from 2/4 sources
Promise.race() — First to Settle Wins
Promise.race() returns the result of the first promise to settle — whether it resolves or rejects. The remaining promises continue running in the background but their results are ignored.
Key characteristics:
- Settles with the first promise to settle (resolve OR reject)
- Other promises continue running but their results are ignored
- Perfect for timeout patterns and fastest response selection
Example 6: Race — First Settler Wins
function task(name, delay, shouldFail = false) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldFail) reject(new Error(`${name} failed`));
else resolve(`${name} completed in ${delay}ms`);
}, delay);
});
}
// Fastest resolver wins
Promise.race([
task("Server A", 400),
task("Server B", 150),
task("Server C", 300)
]).then(winner => {
console.log("🏆 Winner:", winner);
});
🏆 Winner: Server B completed in 150ms
Example 7: Implementing Timeout with Promise.race
function timeout(ms) {
return new Promise((_, reject) => {
setTimeout(() => reject(new Error(`⏰ Timed out after ${ms}ms`)), ms);
});
}
function slowAPI() {
return new Promise(resolve => {
setTimeout(() => resolve({ data: "API Response" }), 3000);
});
}
function fastAPI() {
return new Promise(resolve => {
setTimeout(() => resolve({ data: "Quick Response" }), 200);
});
}
// Case 1: API is too slow — timeout wins
async function example1() {
try {
const result = await Promise.race([slowAPI(), timeout(1000)]);
console.log("Got result:", result);
} catch (error) {
console.log("Case 1:", error.message);
}
}
// Case 2: API responds in time
async function example2() {
try {
const result = await Promise.race([fastAPI(), timeout(1000)]);
console.log("Case 2: Got result:", JSON.stringify(result));
} catch (error) {
console.log("Error:", error.message);
}
}
example1();
example2();
Case 2: Got result: {"data":"Quick Response"}
Case 1: ⏰ Timed out after 1000msExample 8: Race Where Rejection Comes First
const quickFail = new Promise((_, reject) => {
setTimeout(() => reject(new Error("Quick failure")), 50);
});
const slowSuccess = new Promise(resolve => {
setTimeout(() => resolve("Slow success"), 200);
});
Promise.race([quickFail, slowSuccess])
.then(value => console.log("Resolved:", value))
.catch(error => console.log("Rejected:", error.message));
Important: In Promise.race, if rejection comes first, the race rejects. If you only want successful results, use Promise.any().
Promise.any() — First to Resolve Wins
Promise.any() returns the result of the first promise to resolve (fulfill). It ignores rejections. It only rejects when all promises reject — then it throws an AggregateError.
Key characteristics:
- Resolves with the first fulfilled value (skips rejections)
- Only rejects when ALL promises reject
- Rejection gives
AggregateError with .errors array containing all reasons - Added in ES2021
Example 9: First Successful Response
const promises = [
new Promise((_, reject) => setTimeout(() => reject(new Error("Server 1 down")), 100)),
new Promise((_, reject) => setTimeout(() => reject(new Error("Server 2 down")), 200)),
new Promise(resolve => setTimeout(() => resolve("Server 3 responded!"), 300)),
new Promise(resolve => setTimeout(() => resolve("Server 4 responded!"), 400))
];
Promise.any(promises)
.then(firstSuccess => {
console.log("✅ First successful:", firstSuccess);
console.log("(Rejections from Server 1 & 2 were ignored)");
});
✅ First successful: Server 3 responded!
(Rejections from Server 1 & 2 were ignored)
Example 10: All Promises Reject — AggregateError
const allFail = [
Promise.reject(new Error("DB Error")),
Promise.reject(new Error("Cache Error")),
Promise.reject(new Error("API Error"))
];
Promise.any(allFail)
.then(value => console.log("Success:", value))
.catch(error => {
console.log("Type:", error.constructor.name);
console.log("Message:", error.message);
console.log("\nAll errors:");
error.errors.forEach((err, i) => {
console.log(` [${i}]: ${err.message}`);
});
});
Type: AggregateError
Message: All promises were rejected
All errors:
[0]: DB Error
[1]: Cache Error
[2]: API Error
Example 11: Fallback CDN Pattern with Promise.any
function fetchFromCDN(cdnName, delay, shouldFail) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldFail) {
reject(new Error(`${cdnName}: 503 Service Unavailable`));
} else {
resolve({ cdn: cdnName, asset: "bundle.js", size: "245KB" });
}
}, delay);
});
}
async function loadAsset() {
try {
const result = await Promise.any([
fetchFromCDN("CloudFront", 200, true), // Down
fetchFromCDN("Cloudflare", 150, true), // Down
fetchFromCDN("Fastly", 300, false), // Works!
fetchFromCDN("Akamai", 250, false) // Works but slower than Fastly? No, 250 < 300
]);
console.log(`✅ Loaded from: ${result.cdn}`);
console.log(` Asset: ${result.asset} (${result.size})`);
} catch (error) {
console.log("❌ All CDNs failed!");
console.log("Errors:", error.errors.length);
}
}
loadAsset();
✅ Loaded from: Akamai
Asset: bundle.js (245KB)
Real-World Code Examples
Example 12: Parallel API Calls with Error Handling
async function fetchUserDashboard(userId) {
const apis = {
profile: `https://api.example.com/users/${userId}`,
orders: `https://api.example.com/orders?user=${userId}`,
notifications: `https://api.example.com/notifications?user=${userId}`
};
// Simulate API calls
function simulateFetch(name, delay) {
return new Promise(resolve => {
setTimeout(() => resolve({ endpoint: name, status: 200, items: 5 }), delay);
});
}
const start = Date.now();
const [profile, orders, notifications] = await Promise.all([
simulateFetch("profile", 200),
simulateFetch("orders", 350),
simulateFetch("notifications", 150)
]);
const elapsed = Date.now() - start;
console.log(`Dashboard loaded in ${elapsed}ms`);
console.log(`Profile: ${profile.status} OK`);
console.log(`Orders: ${orders.items} items`);
console.log(`Notifications: ${notifications.items} items`);
}
fetchUserDashboard(42);
Dashboard loaded in 350ms
Profile: 200 OK
Orders: 5 items
Notifications: 5 items
Example 13: Loading Spinner with Timeout Using Race
function fetchData() {
return new Promise(resolve => {
setTimeout(() => resolve({ users: ["Alice", "Bob", "Charlie"] }), 800);
});
}
function showLoadingAfter(ms) {
return new Promise(resolve => {
setTimeout(() => resolve("SHOW_SPINNER"), ms);
});
}
async function loadWithSpinner() {
// If data takes > 300ms, show spinner
const raceResult = await Promise.race([
fetchData().then(data => ({ type: "DATA", data })),
showLoadingAfter(300).then(() => ({ type: "SPINNER" }))
]);
if (raceResult.type === "SPINNER") {
console.log("⏳ Showing loading spinner...");
// Data is still loading, await it separately
const data = await fetchData();
console.log("✅ Data arrived:", data.users.join(", "));
console.log("🔄 Hiding spinner");
} else {
console.log("⚡ Data loaded instantly:", raceResult.data.users.join(", "));
}
}
loadWithSpinner();
⏳ Showing loading spinner...
✅ Data arrived: Alice, Bob, Charlie
🔄 Hiding spinner
Example 14: Comprehensive Error Handling Patterns
// Pattern 1: Promise.all with individual error wrapping
async function safeAll(promises) {
const wrapped = promises.map(p =>
p.then(value => ({ success: true, value }))
.catch(error => ({ success: false, error: error.message }))
);
return Promise.all(wrapped);
}
const results = await safeAll([
Promise.resolve("Data A"),
Promise.reject(new Error("Failed B")),
Promise.resolve("Data C")
]);
console.log("Safe Promise.all results:");
results.forEach((r, i) => {
if (r.success) {
console.log(` [${i}] ✅ ${r.value}`);
} else {
console.log(` [${i}] ❌ ${r.error}`);
}
});
// Pattern 2: Retry with Promise.any
async function fetchWithRetries(url, maxRetries = 3) {
const attempts = Array.from({ length: maxRetries }, (_, i) =>
new Promise((resolve, reject) => {
setTimeout(() => {
if (i < 2) reject(new Error(`Attempt ${i + 1} failed`));
else resolve(`Success on attempt ${i + 1}`);
}, (i + 1) * 100);
})
);
try {
const result = await Promise.any(attempts);
console.log("\n" + result);
} catch (error) {
console.log("All retries failed:", error.errors.length, "attempts");
}
}
fetchWithRetries("https://api.example.com/data");
Safe Promise.all results:
[0] ✅ Data A
[1] ❌ Failed B
[2] ✅ Data C
Success on attempt 3
Example 15: Batch Processing with Concurrency Control
async function batchProcess(items, batchSize, processFn) {
const results = [];
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
const batchNum = Math.floor(i / batchSize) + 1;
console.log(`📦 Batch ${batchNum}: Processing ${batch.length} items...`);
const batchResults = await Promise.all(
batch.map(item => processFn(item))
);
results.push(...batchResults);
}
return results;
}
// Process 9 items in batches of 3
const items = [1, 2, 3, 4, 5, 6, 7, 8, 9];
function processItem(id) {
return new Promise(resolve => {
setTimeout(() => resolve(`Item ${id} done`), 50);
});
}
batchProcess(items, 3, processItem).then(results => {
console.log(`\n✅ All done: ${results.length} items processed`);
console.log("Last 3:", results.slice(-3).join(", "));
});
📦 Batch 1: Processing 3 items...
📦 Batch 2: Processing 3 items...
📦 Batch 3: Processing 3 items...
✅ All done: 9 items processed
Last 3: Item 7 done, Item 8 done, Item 9 done
When to Use Which — Comparison Table
| Scenario | Best Method | Why |
|---|
| Load multiple APIs where ALL data is needed | Promise.all() | Fail-fast if any fails — all data or nothing |
| Load multiple APIs where partial data is OK | Promise.allSettled() | Get whatever succeeds, handle failures separately |
| Implement request timeout | Promise.race() | Race between fetch and timeout timer |
| Pick fastest CDN/mirror | Promise.any() | First successful response wins, ignore failures |
| Validate all inputs before submission | Promise.all() | All validations must pass |
| Health check multiple servers | Promise.allSettled() | Need status of ALL servers, not just first failure |
| Show loading spinner after delay | Promise.race() | Race between data arrival and delay timer |
| Try multiple auth providers | Promise.any() | First successful login wins |
| Download assets from primary + fallback | Promise.any() | Use first available source |
| Aggregate analytics from multiple sources | Promise.allSettled() | Collect whatever is available |
Decision Flowchart (Text)
Do you need ALL promises to succeed?
├── YES → Do you want fail-fast on first error?
│ ├── YES → Promise.all()
│ └── NO → Promise.allSettled() + filter fulfilled
└── NO → Do you need just ONE promise?
├── YES → Must that one be successful (fulfilled)?
│ ├── YES → Promise.any()
│ └── NO → Promise.race()
└── NO → Promise.allSettled()
Common Mistakes
Mistake 1: Forgetting Promise.all Rejects on First Failure
// ❌ WRONG: Assuming you'll get partial results from Promise.all
Promise.all([api1(), api2(), api3()])
.then(([a, b, c]) => {
// If api2() fails, this NEVER runs
// You lose results from api1() and api3() too!
renderDashboard(a, b, c);
});
// ✅ CORRECT: Use allSettled for partial results
Promise.allSettled([api1(), api2(), api3()])
.then(results => {
const data = results
.filter(r => r.status === "fulfilled")
.map(r => r.value);
renderDashboard(data); // Works with whatever succeeded
});
Mistake 2: Not Handling AggregateError from Promise.any
// ❌ WRONG: Generic catch without AggregateError handling
Promise.any([p1, p2, p3]).catch(error => {
console.log(error.message); // "All promises were rejected" — not helpful
});
// ✅ CORRECT: Access individual errors
Promise.any([p1, p2, p3]).catch(error => {
if (error instanceof AggregateError) {
error.errors.forEach(err => console.log("Detail:", err.message));
}
});
Mistake 3: Using Promise.race for "First Success" (Use Promise.any Instead)
// ❌ WRONG: race returns first SETTLEMENT (could be rejection!)
const result = await Promise.race([
fetch(unreliableServer), // Might reject fast
fetch(reliableServer) // Slower but reliable
]);
// If unreliable rejects first, you get an error even though reliable would work!
// ✅ CORRECT: Use Promise.any for first SUCCESS
const result = await Promise.any([
fetch(unreliableServer),
fetch(reliableServer)
]);
// Ignores the fast rejection, waits for reliable server
Mistake 4: Passing Non-Iterable to Promise Methods
// ❌ WRONG: Passing individual promises, not an array
Promise.all(promise1, promise2, promise3); // Only considers promise1!
// ✅ CORRECT: Pass an array
Promise.all([promise1, promise2, promise3]);
// ❌ MISCONCEPTION: Thinking promises start when Promise.all is called
const promises = [
fetch("/api/users"), // Already started!
fetch("/api/posts"), // Already started!
fetch("/api/comments") // Already started!
];
// Promise.all doesn't "start" them — they're already running
// Promise.all just waits for all to complete
const results = await Promise.all(promises);
// ✅ UNDERSTANDING: If you want to control when they start,
// wrap in functions and call inside Promise.all
const results2 = await Promise.all([
(() => fetch("/api/users"))(),
(() => fetch("/api/posts"))(),
(() => fetch("/api/comments"))()
]);
Mistake 6: Forgetting that Promise.race Does NOT Cancel Other Promises
// ❌ MISCONCEPTION: Other promises are cancelled after race settles
const result = await Promise.race([
fetchLargeFile(), // 10 MB download continues in background!
timeout(1000)
]);
// Even if timeout wins, the large file download keeps running
// (consuming bandwidth and memory)
// ✅ CORRECT: Use AbortController to actually cancel
const controller = new AbortController();
const result2 = await Promise.race([
fetch("/large-file", { signal: controller.signal }),
new Promise((_, reject) => setTimeout(() => {
controller.abort(); // Actually cancels the fetch!
reject(new Error("Timeout"));
}, 1000))
]);
Key Takeaways
Promise.all() = "ALL or nothing" — perfect jab saara data mandatory ho (like form validation, required API data)
Promise.allSettled() = "Best effort" — never rejects, use when partial success is acceptable
Promise.race() = "Fastest wins" (whether resolve or reject) — ideal for timeout patterns
Promise.any() = "First success wins" (ignores rejections) — for fallback/redundancy patterns
- Order preserved —
Promise.all() and Promise.allSettled() return results in the same order as the promises were passed (regardless of completion order)
- All methods accept iterables — Array, Set, or any iterable of promises (non-promise values are auto-wrapped with
Promise.resolve())
- Empty iterable edge cases:
Promise.all([]) resolves with [], Promise.race([]) stays pending forever, Promise.any([]) rejects with AggregateError
- Promises start immediately — these methods don't "start" promises. Promises begin executing as soon as they are created
- No cancellation — Even after
Promise.race() settles, other promises continue running in the background. Use AbortController for cancellation
- Error handling strategy: Always use
.catch() or try/catch with Promise.all; .catch() is not necessary with Promise.allSettled (since it never rejects)
Interview Questions
Q1: What is the difference between Promise.all and Promise.allSettled?
Answer: Promise.all() rejects immediately when ANY promise rejects (fail-fast) and you lose all results. Promise.allSettled() waits for ALL promises to settle and NEVER rejects — it returns an array of objects with status: "fulfilled" or status: "rejected" for each promise.
// Promise.all — one failure kills everything
Promise.all([Promise.resolve(1), Promise.reject("err"), Promise.resolve(3)])
.catch(e => console.log("all:", e)); // "err"
// Promise.allSettled — always succeeds with full status
Promise.allSettled([Promise.resolve(1), Promise.reject("err"), Promise.resolve(3)])
.then(r => console.log("allSettled:", r.map(x => x.status)));
// ["fulfilled", "rejected", "fulfilled"]
all: err
allSettled: [ 'fulfilled', 'rejected', 'fulfilled' ]
Q2: What happens when you pass an empty array to each Promise method?
Answer:
Promise.all([]) → Resolves immediately with []Promise.allSettled([]) → Resolves immediately with []Promise.race([]) → Stays pending forever (never settles)Promise.any([]) → Rejects with AggregateError (no promise to fulfill)
Promise.all([]).then(v => console.log("all:", v));
Promise.allSettled([]).then(v => console.log("allSettled:", v));
// Promise.race([]) — never resolves, would hang
Promise.any([]).catch(e => console.log("any:", e.constructor.name));
all: []
allSettled: []
any: AggregateError
Q3: How would you implement a timeout for a fetch request?
Answer: Use Promise.race() between the fetch and a timeout promise:
function fetchWithTimeout(url, ms) {
return Promise.race([
fetch(url).then(r => r.json()),
new Promise((_, reject) =>
setTimeout(() => reject(new Error("Timeout")), ms)
)
]);
}
// Better version with AbortController (actually cancels the request):
function fetchWithTimeoutV2(url, ms) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), ms);
return fetch(url, { signal: controller.signal })
.then(r => r.json())
.finally(() => clearTimeout(timeoutId));
}
Q4: What is AggregateError and when does it occur?
Answer: AggregateError is thrown by Promise.any() when ALL promises reject. It has an .errors property containing an array of all rejection reasons.
Promise.any([
Promise.reject(new Error("A failed")),
Promise.reject(new Error("B failed")),
Promise.reject(new Error("C failed"))
]).catch(error => {
console.log(error instanceof AggregateError); // true
console.log(error.message); // "All promises were rejected"
console.log(error.errors.length); // 3
console.log(error.errors[0].message); // "A failed"
});
true
All promises were rejected
3
A failed
Q5: What is the difference between Promise.race and Promise.any?
Answer:
Promise.race() — first promise to settle (resolve OR reject) winsPromise.any() — first promise to fulfill (resolve only) wins, rejections are ignored
const fast_reject = new Promise((_, rej) => setTimeout(() => rej("err"), 50));
const slow_resolve = new Promise(res => setTimeout(() => res("ok"), 200));
Promise.race([fast_reject, slow_resolve])
.catch(e => console.log("race result:", e)); // "err" (rejection was faster)
Promise.any([fast_reject, slow_resolve])
.then(v => console.log("any result:", v)); // "ok" (ignores rejection)
race result: err
any result: ok
Q6: How does Promise.all preserve order?
Answer: Results are always in the SAME order as input promises, regardless of which resolves first:
const slow = new Promise(res => setTimeout(() => res("SLOW"), 500));
const fast = new Promise(res => setTimeout(() => res("FAST"), 100));
const medium = new Promise(res => setTimeout(() => res("MEDIUM"), 300));
Promise.all([slow, fast, medium]).then(results => {
console.log(results);
// ["SLOW", "FAST", "MEDIUM"] — same order as input, NOT completion order
});
[ 'SLOW', 'FAST', 'MEDIUM' ]
Q7: Can you pass non-Promise values to Promise.all?
Answer: Yes! Non-promise values are automatically wrapped in Promise.resolve():
Promise.all([42, "hello", true, Promise.resolve("actual promise")])
.then(results => {
console.log(results);
console.log("All are resolved values, not promises");
});
[ 42, 'hello', true, 'actual promise' ]
All are resolved values, not promises
FAQ
1. Does Promise.all execute promises in parallel?
Answer: Not technically. JavaScript is single-threaded. Promise.all() doesn't "start" promises — promises begin execution as soon as they are created. Promise.all() simply *waits* for all of them to settle.
2. If one promise rejects in Promise.race, do the other promises get cancelled?
Answer: No! In JavaScript, promises cannot be cancelled. Even after Promise.race() settles, other promises continue running in the background. Use AbortController to free resources.
3. Where should Promise.allSettled be used instead of Promise.all?
Answer: Jab aapko partial success acceptable ho:
- When loading a dashboard where some widgets might fail
- When collecting data from multiple analytics sources
- When running health checks where you need everyone's status
- In batch operations where some items might fail but the rest should still be processed
4. What is the browser support for Promise.any?
Answer: Promise.any() was introduced in ES2021 (ES12). All modern browsers support it (Chrome 85+, Firefox 79+, Safari 14+, Edge 85+). It's also available in Node.js 15+. For older environments, use a polyfill.
Answer: Yes! Promise.all([]) immediately resolves with []. But note:
Promise.race([]) — never settles (forever pending)Promise.any([]) — immediately rejects with AggregateError
These edge cases are commonly asked in interviews. The logic: in all, the "all zero promises fulfilled" condition is vacuously true; in race, there's no promise to race; and in any, there's no promise that can fulfill, so it rejects.