Як працює ланцюжок промісів?
Що таке ланцюжок промісів
Ланцюжок промісів - це послідовне виконання асинхронних дій,
де результат одного .then() передається наступному.
Кожен .then(), .catch() та .finally() повертає новий проміс,
що дозволяє вибудувати лінійний потік обробки - без "callback hell".
Приклад базового ланцюжка
new Promise((resolve) => {
setTimeout(() => resolve(10), 1000);
})
.then((num) => {
console.log('1. Отримали:', num);
return num * 2;
})
.then((num) => {
console.log('2. Помножили:', num);
return num + 5;
})
.then((result) => {
console.log('3. Підсумок:', result);
});Вивід:
1. Отримали: 10
2. Помножили: 20
3. Підсумок: 25Кожен .then():
- отримує результат попереднього кроку,
- повертає новий проміс,
- передає його результат далі по ланцюжку.
Як це працює під капотом
- Перший проміс створюється і переходить у
pending. Коли викликаєтьсяresolve(value), він стаєfulfilled. - Перший
.then()отримуєvalue, і повертає новий проміс, який тепер очікує наступний результат. - Кожен
.then()у ланцюжку дочікується виконання попереднього, навіть якщо всередині повертається новий проміс.
Приклад з асинхронним кроком
Promise.resolve(1)
.then((n) => {
console.log('A:', n);
return new Promise((resolve) =>
setTimeout(() => resolve(n + 1), 1000)
);
})
.then((n) => {
console.log('B:', n);
return n * 3;
})
.then((n) => console.log('C:', n));Вивід (через секунду):
A: 1
B: 2
C: 6Тут:
.then()"розпізнає", що йому повернули новий проміс,- чекає, поки він завершиться (
resolve), - і тільки потім виконує наступний крок ланцюжка.
Помилки в ланцюжку
Якщо в будь-якому .then() станеться помилка (throw або reject),
усі наступні .then() пропускаються,
і керування переходить у перший найближчий .catch().
Promise.resolve(10)
.then((x) => x / 2)
.then(() => {
throw new Error('Помилка!');
})
.then(() => console.log('не виконається'))
.catch((err) => console.error('Спіймали:', err.message))
.then(() => console.log('продовжуємо'));Вивід:
Спіймали: Помилка!
продовжуємоПовернення значень і промісів у .then()
Що повертає .then() | Що станеться |
|---|---|
| Звичайне значення | Обгортається у Promise.resolve(value) |
| Проміс | Ланцюжок чекає, поки він завершиться |
| Помилка (throw) | Ланцюжок переходить у rejected |
| Нічого не повертає | Передає undefined далі |
Приклад комбінування
Promise.resolve('A')
.then((v) => v + 'B') // поверне 'AB'
.then((v) => Promise.resolve(v + 'C')) // чекає інший проміс
.then((v) => v + 'D')
.then(console.log); // ABDCМожна використовувати .catch() у середині ланцюжка
Promise.reject('Помилка')
.catch((err) => {
console.log('Спіймали:', err);
return 'Відновлено';
})
.then((v) => console.log('Далі:', v));Вивід:
Спіймали: Помилка
Далі: Відновлено.catch() теж повертає новий проміс,
тому після обробки помилки ланцюжок продовжується.
.finally() у ланцюжку
finally() виконується завжди, незалежно від результату,
і не змінює значення (якщо не кидає помилку):
Promise.resolve('OK')
.finally(() => console.log('Очищення...'))
.then(console.log);Вивід:
Очищення...
OKПриклад повного ланцюжка з помилками
Promise.resolve(1)
.then((x) => x + 1)
.then(() => {
throw new Error('Ой!');
})
.catch((e) => {
console.log('Помилку спіймано:', e.message);
return 5;
})
.then((x) => console.log('Результат:', x))
.finally(() => console.log('Готово'));Вивід:
Помилку спіймано: Ой!
Результат: 5
ГотовоПроста аналогія
Уяви ланцюжок промісів як конвеєр.
- Кожен
.then()- це станція, де деталь обробляється; - Якщо щось пішло не так -
.catch()виправляє помилку і повертає на конвеєр; - Наприкінці
.finally()вимикає станки і підмітає підлогу.
Підсумок
| Особливість | Опис |
|---|---|
Кожен .then() | Повертає новий проміс |
| Значення передаються далі | Результат з .then() йде в наступний |
| Помилки | Передаються далі до найближчого .catch() |
.finally() | Виконується в будь-якому разі |
| Ланцюжок | Дозволяє писати асинхронний код лінійно і без вкладеності |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.