Devs Hive
Повернутися до всіх запитань

Яка різниця між Promise.all i Promise.allSettled?

JavaScriptJuniorMiddle
Зустрічали на інтервʼю:2 користувачів

Обидва методи працюють із масивом промісів: вони запускають їх паралельно та очікують на їх завершення. Проте ці методи поводяться по-різному, тому і на співбесідах, і в реальній роботі важливо розуміти різницю між ними та знати, у яких ситуаціях який метод доречніший.

Promise.all

Цей метод приймає масив промісів і повертає масив з результатами в тому ж порядку, в якому ми передали проміси. Якщо всі вони завершилися успішно, то Promise.all завершується успіхом (fulfilled), але якщо хоча б один був відхилений (rejected), Promise.all відразу завершується з помилкою і не очікує проміси, яка в процесі виконання (pending).

async function loadProducts() {
const ids = [1, 2, 3];

const products = await Promise.all(
ids.map(async (id) => {
const res = await fetch(`https://api.example.com/products/${id}`);
return res.json();
})
);

console.log(products); // масив з 3 продуктів
/*
[
{
"id": 1,
"name": "iPhone 15",
"price": 999
},
{
"id": 2,
"name": "MacBook Air",
"price": 1299
},
{
"id": 3,
"name": "AirPods Pro",
"price": 249
}
]
*/
}

loadProducts();

Promise.allSettled

Теж запускає масив промісів паралельно, але очікує доки всі завершаться fulfilled/rejected, після чого повертає масив обʼєктів з даними або причиною помилки. Як можна побачити з відповіді від API, Promise.allSettled завершився успішно, навіть маючи rejected проміс. Це і є різниця між Promise.all і Promise.allSettled.

const upload = (file) =>
fetch("/photos", { method: "POST", body: file }).then((r) => {
if (!r.ok) throw new Error("Upload failed");
return r.json();
});

Promise.allSettled([
upload(file1),
upload(file2),
Promise.reject(new Error("Network error"))
]).then((results) => console.log(results));

/*
Приклад відповіді (від Promise.allSettled):

[
{
"status": "fulfilled",
"value": { "id": "ph_101", "url": "https://cdn.example.com/ph_101.jpg" }
},
{
"status": "fulfilled",
"value": { "id": "ph_102", "url": "https://cdn.example.com/ph_102.jpg" }
},
{
"status": "rejected",
"reason": "Error: Network error"
}
]
*/

Коли і що використовувати

Promise.all найкраще використовувати для ідемпотентних операцій. Так як у випадку rejected ми без всяких проблем зможемо зробити Retry і перезапустити всі проміси. Найчастіше це отримання або оновлення даних. Якщо ви не знаєте, що таке ідемпотентність, то рекомендую почитати тут, так як це теж запитання на Node.js інтервʼю.

Promise.allSettled найкраще використовувати при створенні сутностей. Так як стан системи змінюється, ми не можемо зробити простий Retry для всіх промісів. А за допомогою allSettled ми зможемо вибрати проміси, які завершилися rejected, і перезапустити їх окремо.

Простим прикладом використання allSettled є завантаження багатьох картинок в галерею. Наприклад, ви завантажуєте одночасно 10 фотографій, і 7 з них завантажилися успішно, а три - з помилкою. Тоді ми можемо показати користувачу, що є проблеми з трьома картинками, і він зможе або видалити їх, або спробувати завантажити знову.

Зустрічав на інтервʼю?

Коментарі (0)

Увійдіть, щоб залишити коментар

Поки що немає коментарів. Будьте першим!