JavaScript
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
61: Promise.all, allSettled, race, and any
Alright, let's get into this. Imagine we're building a user dashboard. To get the page ready, we need to fetch three things: the user's profile, their recent orders, and their notification settings. We could just await each one sequentially, but that's a waste of time. Why wait for the profile to finish before even starting the order request?
Trying to speed things up
The obvious move is to fire them all off at once. I'll throw them into an array and use Promise.all. This is usually the go-to for "I need all of this data before I can render the UI."
const fetchDashboardData = async () => {
const profilePromise = fetch('/api/profile');
const ordersPromise = fetch('/api/orders');
const settingsPromise = fetch('/api/settings');
try {
const [profile, orders, settings] = await Promise.all([
profilePromise,
ordersPromise,
settingsPromise
]);
console.log('Everything loaded!', { profile, orders, settings });
} catch (error) {
console.error('Something went wrong:', error);
}
};
This looks great on paper. It's fast because the requests happen in parallel. But here's the catch: Promise.all is "fail-fast." I just tried this in my local environment and intentionally broke the /api/settings endpoint. Even though the profile and orders came back perfectly, the whole thing jumped straight to the catch block. The user sees a total error page just because their notification settings failed to load. That's a bad user experience.
Handling partial failures
I don't actually need the settings to render the profile or the orders. I just want whatever actually worked. This is where Promise.allSettled comes in. Let's swap it out and see how the output changes.
const fetchDashboardData = async () => {
const promises = [
fetch('/api/profile'),
fetch('/api/orders'),
fetch('/api/settings')
];
const results = await Promise.allSettled(promises);
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`Request ${index} succeeded:`, result.value);
} else {
console.log(`Request ${index} failed:`, result.reason);
}
});
};
Notice the difference? No try/catch block is strictly necessary here because allSettled never rejects; it just tells you the outcome of every single promise. It gives us an array of objects with a status of either 'fulfilled' or 'rejected'. Now, I can render the profile and orders, and maybe just show a little warning icon where the settings should be. Much better.
The race for the fastest response
Now, let's change the scenario. Say we have our data mirrored on two different servers—a primary and a backup—to ensure low latency. We don't need both; we just want whichever one responds first. This feels like a race.
const fastFetch = async () => {
const primaryServer = fetch('https://primary.api.com/data');
const backupServer = fetch('https://backup.api.com/data');
try {
const fastest = await Promise.race([primaryServer, backupServer]);
console.log('Winner:', fastest);
} catch (error) {
console.error('The fastest one failed:', error);
}
};
Promise.race is simple: the first promise to settle (whether it succeeds or fails) wins. But wait—I just noticed a flaw. If the primary server is incredibly fast but returns a 404 Error, Promise.race will resolve with that failure immediately. It won't wait for the backup server to potentially provide a successful response. It's literally a race to the finish line, regardless of whether the finish line is a trophy or a cliff.
Finding the first success
If I only care about the first successful response and want to ignore the failures unless everything fails, Promise.any is the tool I'm looking for. It's like the opposite of Promise.all.
const reliableFetch = async () => {
const primaryServer = fetch('https://primary.api.com/data');
const backupServer = fetch('https://backup.api.com/data');
try {
const firstSuccess = await Promise.any([primaryServer, backupServer]);
console.log('First successful response:', firstSuccess);
} catch (error) {
console.log('All servers failed');
// Promise.any throws an AggregateError when all promises reject
}
};
Now, if the primary server crashes, JavaScript just ignores it and waits for the backup. It only throws an error if every single promise in the array rejects. It's a much more resilient pattern for redundancy.
📋 Practical Task
Build a Multi-Source Image Resolver
You are building a gallery that loads images from three different CDN mirrors to ensure the user sees the image as quickly as possible. Some mirrors might be down, and some might be slow.
Your Task:
- Create a function
resolveImage(urls)that takes an array of image URLs. - Use the appropriate
Promisemethod to return the first successfully resolved URL from the list. - If all mirrors fail, the function should catch the error and return a string:
"fallback-image.jpg". - To simulate the network, create a helper function
mockFetch(url)that randomly returns a resolved promise (success) or a rejected promise (failure) after a random delay between 100ms and 1000ms.
There are no comments for now.