Промисы
Промис (от английского promise — обещание) — это объект, который обещает результат в будущем. Пока действие не завершено, результата ещё нет; когда оно закончится, промис либо выполнится со значением, либо завершится ошибкой. На промисах построена вся современная асинхронная работа: запросы к серверу, чтение файлов, ожидание.
then
Чтобы получить результат промиса, в метод then() передают функцию. Она будет вызвана, когда значение появится:
const promise = Promise.resolve(42);
promise.then((value) => {
console.log(value); // 42
});Promise.resolve() создаёт уже выполненный промис — так удобно показать then() без лишнего кода.
Состояния промиса
У промиса три состояния. Из ожидания он переходит в одно из двух конечных и больше не меняется:
| Состояние | Что значит |
|---|---|
| pending — ожидание | Результата ещё нет |
| fulfilled — выполнен | Есть значение, вызываются функции из then() |
| rejected — отклонён | Произошла ошибка, вызываются функции из catch() |
Создание промиса
Свой промис создают через new Promise(). Внутрь передают функцию, которая вызывает resolve, когда результат готов:
const promise = new Promise((resolve) => {
setTimeout(() => {
resolve('Готово');
}, 300);
});
promise.then((value) => {
console.log(value); // Готово
});Этот промис выполняется через 300 мс. Так оборачивают в промис старые функции, которые принимают колбэк.
Ошибки и catch
Второй параметр — reject — отклоняет промис с ошибкой. Перехватывает её метод catch():
const promise = new Promise((resolve, reject) => {
reject(new Error('Сервер не отвечает'));
});
promise.catch((error) => {
console.log(error.message); // Сервер не отвечает
});Отклонённый промис без catch() оставляет в консоли сообщение Uncaught (in promise).
Цепочки
then() сам возвращает новый промис, поэтому вызовы выстраивают в цепочку. То, что вернула одна функция, получает следующая:
Promise.resolve(2)
.then((value) => value * 10)
.then((value) => value + 1)
.then((value) => {
console.log(value); // 21
});Один catch() в конце цепочки перехватит ошибку из любого её звена.
finally
Функция из finally() выполняется в любом случае — и при успехе, и при ошибке. Туда помещают завершающие действия, например скрытие индикатора загрузки:
Promise.reject(new Error('Нет связи'))
.catch((error) => console.log(error.message))
.finally(() => console.log('Загрузка окончена'));
// Нет связи
// Загрузка оконченаЧастая ошибка
Забыть return внутри then(), если функция записана с фигурными скобками. Тогда следующее звено цепочки получит undefined:
Promise.resolve(5)
.then((value) => {
value * 2;
})
.then((result) => {
console.log(result); // undefined
});Пишите return value * 2 или используйте короткую стрелку без скобок: (value) => value * 2.