JavaScript Promises Tutorial - Section 3: Static Methods
Promise.all() takes an array of Promises and returns a single Promise that:
Promise.all([promise1, promise2, promise3])
.then(results => {
// results is an array: [result1, result2, result3]
})
.catch(error => {
// First rejection
});
const user1 = fetchUser(1);
const user2 = fetchUser(2);
const user3 = fetchUser(3);
Promise.all([user1, user2, user3])
.then(users => {
console.log('All users:', users);
// users = [userData1, userData2, userData3]
})
.catch(error => {
console.error('Failed to fetch users:', error);
});
Results array matches the order of input Promises:
Promise.all([
delay(1000, 'third'), // Takes longest
delay(100, 'first'), // Finishes first
delay(500, 'second') // Finishes second
])
.then(results => {
console.log(results); // ['third', 'first', 'second']
// Order matches input, not completion time!
});
Sequential (Slow):
const user = await fetchUser(1); // Wait 1s
const posts = await fetchPosts(1); // Wait 1s
const comments = await fetchComments(1); // Wait 1s
// Total: 3 seconds
Parallel (Fast):
const [user, posts, comments] = await Promise.all([
fetchUser(1),
fetchPosts(1),
fetchComments(1)
]);
// Total: 1 second (all run simultaneously)
Performance Gain: 3x faster! 🚀
Promise.all() rejects immediately when ANY Promise rejects:
Promise.all([
Promise.resolve('Success 1'),
Promise.reject(new Error('Failed!')),
Promise.resolve('Success 2')
])
.then(results => {
console.log('All succeeded'); // Never runs
})
.catch(error => {
console.error('One failed:', error.message);
// Rejects immediately with first error
});
async function loadDashboard(userId) {
const [user, notifications, settings, activity] = await Promise.all([
fetchUser(userId),
fetchNotifications(userId),
fetchSettings(userId),
fetchActivity(userId)
]);
return {
user,
notifications,
settings,
activity
};
}
async function processUsers(userIds) {
const users = await Promise.all(
userIds.map(id => fetchUser(id))
);
return users;
}
processUsers([1, 2, 3, 4, 5])
.then(users => console.log('Processed:', users.length));
async function aggregateData() {
const [weather, news, stocks] = await Promise.all([
fetch('https://api.weather.com/current').then(r => r.json()),
fetch('https://api.news.com/headlines').then(r => r.json()),
fetch('https://api.stocks.com/prices').then(r => r.json())
]);
return { weather, news, stocks };
}
function preloadImages(urls) {
const promises = urls.map(url => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = () => reject(new Error(`Failed to load ${url}`));
img.src = url;
});
});
return Promise.all(promises);
}
preloadImages([
'image1.jpg',
'image2.jpg',
'image3.jpg'
])
.then(images => {
console.log('All images loaded:', images.length);
})
.catch(error => {
console.error('Failed to load images:', error);
});
Too many parallel requests can overwhelm servers:
// Bad: 1000 simultaneous requests
const results = await Promise.all(
userIds.map(id => fetchUser(id))
);
// Good: Process in batches
async function batchProcess(items, batchSize, processor) {
const results = [];
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
const batchResults = await Promise.all(
batch.map(processor)
);
results.push(...batchResults);
}
return results;
}
const results = await batchProcess(userIds, 10, fetchUser);
// Bad - runs sequentially
const results = [];
for (const id of userIds) {
results.push(await fetchUser(id));
}
// Good - runs in parallel
const results = await Promise.all(
userIds.map(id => fetchUser(id))
);
// Bad - returns undefined
Promise.all([
fetchUser(1).then(user => {
console.log(user);
})
]);
// Good - returns the value
Promise.all([
fetchUser(1).then(user => {
console.log(user);
return user;
})
]);
Promise.all() runs Promises in parallelNext, we'll learn about async/await - the modern syntax that makes async code even more readable!