Опыт руководства командой молодых фронтенд разработчиков показал, что сейчас при обучении уделяется недостаточно внимание "классу" Promise, а делается ставка на синтаксический сахар async/await. Это не всегда себя оправдывает. Небольшое отступление: во многих источниках, даже на MDN, пишут "объект Promise", но с точки зрения теории ООП, это скорее класс. Но настоящих классов в JS не бывает (даже в новом стандарте это сахар для прототипов), поэтому слово класс я беру в кавычки
Нельзя забывать, что async/await - это способ превратить асинхронные вызовы в "синхронные" - async-функция выполняется асинхронно, но, все await-вызовы внутри будут работать как синхронные, т.е. один за другим. Когда это создаёт неудобства? Когда надо сделать много независимых вызовов на сервер. Предположим мы все их сделаем так:
const f = async () => {
let a = await callServerA();
let b = await callServerB();
let c = await callServerC();
}
Что мы получили в итоге? пока не закончился один серверный вызов, не произойдёт другой. А ведь они могут уйти на сервер одновременно, некоторые браузеры позволяют делать до 9 постоянных подключений. А в новых версиях протокола и того больше. Зачем же заставлять наших пользователей ждать дольше, чем нужно?
И тут на сцену выходит "класс" Promise и его статический метод all. Всё очень просто:
const f = () => {
Promise.all([
callServerA()
callServerB()
callServerC()
])
}
Теперь все вызовы уйдут на сервер почти одновременно. Но давайте разовьём мысль. А что если нам надо сделать что-то с результатами всех трёх вызовов. Предположим, все они возвращают числа, и нам надо их сложить и записать в элемент с id result. Никаких проблем:
const f = () => {
Promise.all([
callServerA()
callServerB()
callServerC()
]).then(([resp1, resp2, resp3]) => {
document.getElementById("result").innerText = resp1 + resp2 + resp3;
});
}
А если нам надо поймать и обработать неудачу любого из промисов? Тоже не проблема:
const f = () => {
Promise.all([
callServerA()
callServerB()
callServerC()
]).cacth(() => console.log("ERROR"))
}
Более того, если вы достаточно творческий человек, вы можете позволить себе даже и такие комбинации:
const f = () => {
Promise.all([
Promise.all([
callServerA(),
callServerE().then(() => { /* Do something with E result */})
])
callServerB()
callServerC()
]).finally(() => console.log("All the requests are done"));
}
Общий вывод: async/await - очень удобный синтаксический сахар, но иногда нужна настоящая асинхронность, и тогда лучше использовать методы "класса" Promise