Різниця між resolve і reject
resolve(value) завершує проміс успішно і робить його fulfilled, а reject(reason) завершує його з помилкою і робить rejected. Обидві функції виводять проміс зі стану pending у кінцевий стан, просто в різні гілки результату.
Теорія
TL;DR
resolve(value)каже «операція вдалася» і передає значення далі в.then().reject(reason)каже «операція провалилася» і передає причину в.catch().- Обидва переводять проміс із
pendingуsettled, змінити стан після цього неможливо. - Повторний виклик будь-якого з них ігнорується без помилки.
.finally()виконується незалежно від того, який із них спрацював.- Якщо в
resolve()передати інший проміс, зовнішній проміс дочекається його, це promise unwrapping.
Швидкий приклад
const promise = new Promise((resolve, reject) => {
const success = Math.random() > 0.5;
if (success) {
resolve('Everything went fine');
} else {
reject('Something went wrong');
}
});
promise
.then(result => console.log('then:', result))
.catch(error => console.log('catch:', error))
.finally(() => console.log('finally'));Можливий вивід:
then: Everything went fine
finallyабо
catch: Something went wrong
finallyЯк вони працюють
| Метод | Що робить | Стан промісу | Що викличе |
|---|---|---|---|
resolve(value) | Завершує проміс успішно, передає значення value | fulfilled | .then(value => ...) |
reject(reason) | Завершує проміс з помилкою, передає reason | rejected | .catch(error => ...) |
Після виклику одного з них:
- проміс «фіксується» (settled),
- повторний виклик
resolveабоrejectбуде проігноровано.
Приклад з resolve
const promise = new Promise((resolve) => {
setTimeout(() => {
resolve('Data received!');
}, 1000);
});
promise.then(result => console.log(result));Через 1 секунду:
Data received!Проміс перейшов у стан fulfilled.
Приклад з reject
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject('Network error');
}, 1000);
});
promise.catch(error => console.error(error));Через 1 секунду:
Network errorПроміс перейшов у стан rejected.
Стан змінюється лише один раз
const promise = new Promise((resolve, reject) => {
resolve('OK');
reject('Error'); // ignored
});
promise.then(console.log).catch(console.error);Після першого виклику (resolve) проміс став fulfilled, тож другий виклик (reject) не має жодного ефекту.
resolve з іншим промісом
Якщо у resolve() передати інший Promise, поточний проміс чекатиме на його завершення.
const inner = new Promise((resolve) => setTimeout(() => resolve('Inner result'), 1000));
const outer = new Promise((resolve) => resolve(inner));
outer.then(console.log); // prints "Inner result" after 1 secondЦе називається promise unwrapping, тобто «розгортання» промісів. reject() так не вміє: переданий у нього проміс стане звичайною причиною відмови, його ніхто не розгортатиме.
Обробка результатів
new Promise((resolve, reject) => {
resolve('OK');
}).then(console.log); // OK
new Promise((resolve, reject) => {
reject('Error');
}).catch(console.error); // ErrorАналогія з доставкою посилки:
resolveце кур'єр привіз посилку, все успішно.rejectце кур'єр зателефонував і сказав «адресу не знайдено», сталася помилка.
Підсумкова таблиця
| Метод | Стан | Що передає | Де обробляється | Аналогія |
|---|---|---|---|---|
resolve(value) | fulfilled | Успішний результат | .then() | Посилку доставлено |
reject(reason) | rejected | Помилку або причину відмови | .catch() | Кур'єр не зміг доставити |
| Після виклику | Проміс стає settled, змінити його вже не можна | Нічого | .finally() | Маршрут закрито |
Типові помилки
- Викликати
resolve()іreject()поруч і чекати, що спрацюють обидва. Виграє перший, другий мовчки ігнорується. - Передавати в
reject()рядок замістьError. Кращеreject(new Error('Network error')): тоді є стек виклику і нормальне повідомлення. - Думати, що
rejectкидає виняток у зовнішній код. Він лише переводить проміс уrejected, а без.catch()це стає unhandled rejection. - Вважати, що після
resolve()код у виконавці зупиняється. Це звичайний виклик функції: рядки нижче виконаються, просто вже нічого не змінять, тому пишітьreturn resolve(value). - Забувати, що
resolve(anotherPromise)чекає. Такий проміс не станеfulfilledодразу, він пов'яже себе з переданим промісом. - Класти обробку помилок тільки в другий аргумент
.then()..then(onOk, onErr)не ловить помилку, кинуту в самомуonOk, а.catch()після нього ловить.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.