Параллельная загрузка данных позволяет выполнять несколько сетевых
запросов одновременно, что существенно ускоряет работу приложения при
необходимости получения большого объёма информации из различных
источников. В JavaScript для этого используются
Promise, async/await, а также
специализированные методы вроде Promise.all,
Promise.allSettled, Promise.race и
Promise.any.
Главная идея заключается в том, чтобы инициировать все запросы одновременно, а не последовательно. Последовательная загрузка блокирует выполнение кода до завершения каждого запроса, что приводит к увеличению времени ожидания.
Promise.allМетод Promise.all принимает массив промисов и возвращает
новый промис, который выполняется тогда, когда все промисы в массиве
выполнены успешно. Если хотя бы один промис завершится с ошибкой,
итоговый промис будет отклонён.
const urls = [
'https://api.example.com/data1',
'https://api.example.com/data2',
'https://api.example.com/data3'
];
const fetchData = async () => {
try {
const responses = await Promise.all(urls.map(url => fetch(url)));
const data = await Promise.all(responses.map(res => res.json()));
console.log(data);
} catch (error) {
console.error('Ошибка при загрузке данных:', error);
}
};
fetchData();
Ключевой момент: Promise.all эффективен
для синхронизации нескольких запросов, когда результат всех запросов
необходим для дальнейшей обработки.
Promise.allSettledPromise.allSettled возвращает массив с результатами всех
промисов, независимо от их успешного завершения. Каждый элемент массива
содержит объект с полями status ("fulfilled"
или "rejected") и value или
reason.
const fetchDataSettled = async () => {
const results = await Promise.allSettled(urls.map(url => fetch(url)));
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`Данные ${index}:`, result.value);
} else {
console.error(`Ошибка ${index}:`, result.reason);
}
});
};
fetchDataSettled();
Ключевой момент: Promise.allSettled
удобен, когда нужно обработать все результаты независимо от ошибок
отдельных запросов.
Promise.race и Promise.anyPromise.race возвращает результат первого
завершившегося промиса (успешного или отклонённого).
Используется для таймаутов и оптимизации загрузки данных.const fetchWithTimeout = async (url, timeout = 5000) => {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
return await response.json();
} finally {
clearTimeout(id);
}
};
const firstResponse = await Promise.race(urls.map(url => fetchWithTimeout(url)));
console.log(firstResponse);
Promise.any возвращает первый успешно
выполненный промис. Если все промисы завершатся ошибкой, метод
вернёт AggregateError.try {
const fastestData = await Promise.any(urls.map(url => fetch(url).then(res => res.json())));
console.log(fastestData);
} catch (error) {
console.error('Все запросы завершились ошибкой', error);
}
Ключевой момент: Promise.any полезен
для получения первого доступного результата из нескольких источников без
остановки при отдельных ошибках.
for…of и mapЧасто возникает необходимость комбинировать параллельную и
последовательную обработку данных. Для этого используют map
с Promise.all для параллельной загрузки и
for…of с await для последовательной
обработки.
const processData = async (urls) => {
const responses = await Promise.all(urls.map(url => fetch(url)));
for (const response of responses) {
const data = await response.json();
console.log(data);
}
};
Ключевой момент: параллельная загрузка уменьшает время ожидания, а последовательная обработка позволяет контролировать поток данных и избежать перегрузки системы.
try/catch для асинхронного кода.p-limit или создают собственные
очереди промисов.Параллельная загрузка данных — это ключевой инструмент для
оптимизации приложений, работающих с большим количеством внешних API.
Использование промисов, методов Promise.all,
Promise.allSettled, Promise.race и
Promise.any позволяет гибко управлять потоками данных,
повышать производительность и улучшать отзывчивость интерфейса.
Правильная обработка ошибок, контроль параллелизма и применение
кэширования делают код стабильным и масштабируемым.