Skip to main content

Promise

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

Теорія

TL;DR

  • Promise представляє майбутній результат асинхронної операції.
  • Стани: pending, далі або fulfilled, або rejected; перехід відбувається лише один раз.
  • resolve(value) переводить у fulfilled, reject(error) - у rejected.
  • Обробка результату: .then(), .catch(), .finally(); кожен із них повертає новий Promise.
  • Комбінатори: Promise.all(), Promise.allSettled(), Promise.race().
  • async/await - це синтаксичний цукор над Promise, а не окремий механізм.

Швидкий приклад

javascript
function fetchData() { return new Promise((resolve) => { setTimeout(() => { resolve('Дані отримано!'); }, 2000); }); } fetchData().then((data) => console.log(data));

fetchData() повертає Promise: через 2 секунди він резолвиться, і then() отримує результат.

Три стани Promise

СтанОписПриклад
pendingочікування, операція ще не завершеназапит у процесі
fulfilledвиконано успішно, є результатдані отримано
rejectedвідхилено, сталася помилкасервер повернув 404

Створення Promise і обробка результату

Promise можна створити вручну:

javascript
const promise = new Promise((resolve, reject) => { const success = Math.random() > 0.5; if (success) { resolve('Успіх!'); } else { reject('Помилка!'); } });
  • resolve(value) переводить Promise у стан fulfilled;
  • reject(error) переводить його у стан rejected.

Результат обробляють ланцюжком методів:

javascript
promise .then((result) => { console.log('Результат:', result); }) .catch((error) => { console.error('Помилка:', error); }) .finally(() => { console.log('Виконується завжди'); });
МетодКоли викликаєтьсяЩо повертає
.then()при успішному виконанні (resolve)новий Promise
.catch()при помилці (reject)новий Promise
.finally()у будь-якому разі (успіх або помилка)новий Promise

Приклад із помилкою:

javascript
function fetchUser() { return new Promise((_, reject) => { setTimeout(() => reject('Користувача не знайдено'), 1000); }); } fetchUser() .then(user => console.log(user)) .catch(err => console.error(err));

Вивід:

text
Користувача не знайдено

Ланцюжки Promise (promise chaining)

Кожен .then() повертає новий Promise, тому асинхронні дії можна вишиковувати в ланцюжок:

javascript
getUser() .then(user => getPosts(user.id)) .then(posts => getComments(posts[0].id)) .then(comments => console.log(comments)) .catch(err => console.error('Помилка:', err));

Перевага: немає вкладеності, код читається згори вниз, на відміну від callback hell.

Для вже готового значення є скорочена форма:

javascript
Promise.resolve('OK').then(console.log); // "OK" Promise.reject('Помилка').catch(console.error); // "Помилка"

Паралельні Promise

Promise.all() чекає, поки виконаються всі

javascript
Promise.all([ fetch('/user'), fetch('/posts'), ]).then(([userRes, postRes]) => { console.log('Обидві відповіді отримано'); });

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

Promise.allSettled() чекає всі, незалежно від помилок

javascript
Promise.allSettled([ fetch('/user'), fetch('/wrong-url'), ]).then(console.log);

Результат:

javascript
[ { status: "fulfilled", value: Response }, { status: "rejected", reason: TypeError } ]

Promise.race() повертає перший, що завершився

javascript
Promise.race([ fetch('/slow'), fetch('/fast'), ]).then(console.log);

Promise і async/await

Promise - це основа, на якій побудований синтаксис async/await:

javascript
async function main() { try { const user = await getUser(); const posts = await getPosts(user.id); console.log(posts); } catch (err) { console.error(err); } }

Тут await просто чекає на Promise, але робить код лінійним і зрозумілим.

Проста аналогія:

Promise схожий на доставку піци. Ви робите замовлення, і Promise створюється у стані pending. Кур'єр везе замовлення, операція виконується. Кур'єр приїхав, Promise переходить у resolve. Кур'єр загубився, Promise переходить у reject. Ви можете «підписатися» на результат через then і обробити помилки через catch.

Підсумок

ТермінОпис
PromiseОб'єкт, що представляє майбутній результат асинхронної операції
Станиpending, далі fulfilled або rejected
Методи.then(), .catch(), .finally()
Головна перевагаСпрощує роботу з асинхронністю, рятує від callback hell
Сучасний синтаксисasync/await побудований на Promise

Типові помилки

  • Думати, що Promise можна «перерезолвити»: після першого resolve або reject стан фіксується назавжди, наступні виклики ігноруються.
  • Вважати, що Promise виконується ліниво. Функція-виконавець стартує одразу в момент new Promise(...), ще до будь-якого .then().
  • Забути return усередині .then(), через що наступна ланка отримує undefined замість даних.
  • Ставити .catch() не в кінці ланцюжка: тоді помилки з наступних .then() залишаться без обробки.
  • Брати Promise.all() там, де потрібен Promise.allSettled(): одна помилка відкидає весь результат, хоча інші запити вже виконалися успішно.
  • Плутати Promise.race() з Promise.any(): race повертає перший завершений результат, навіть якщо це помилка, а any чекає на перший успішний.
  • Загортати в new Promise функцію, яка вже повертає Promise: це зайвий рівень і джерело загублених помилок.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.