Promise.reject() нужен, чтобы получить отклонённый промис. Метод вызывается у Promise, принимает причину ошибки и возвращает промис в состоянии rejected.
Синтаксис
Базовая запись выглядит так:
Promise.reject()
Или так:
Promise.reject(reason)
Где:
reason- причина отклонения промиса: строка, объект ошибки, число, объект или любое другое значение
Что возвращает Promise.reject()
Метод всегда возвращает объект Promise.
const promise = Promise.reject(new Error("boom"));
console.log(promise instanceof Promise); // true
promise.catch((error) => {
console.log(error.message); // "boom"
});
Если передать значение, вы получите промис, который уже считается отклонённым с этим значением.
Простой пример
Promise.reject("Ошибка загрузки").catch((reason) => {
console.log(reason); // "Ошибка загрузки"
});
Это короткий способ создать промис, который уже находится в состоянии ошибки.
Без аргументов Promise.reject() возвращает промис с причиной undefined
Это полезно помнить.
Promise.reject().catch((reason) => {
console.log(reason); // undefined
});
Такой вызов создаёт отклонённый промис без явной причины ошибки.
Обработчики всё равно запускаются не синхронно
Здесь легко ошибиться.
Хотя промис из Promise.reject() уже отклонён, catch() всё равно выполнится не посреди текущего синхронного кода, а позже.
console.log("start");
Promise.reject("boom").catch((reason) => {
console.log(reason); // "boom"
});
console.log("end");
Результат будет таким:
start
end
boom
Поэтому Promise.reject() не делает код синхронным.
Promise.reject() удобно создаёт ошибочный промис из готового значения
Это один из самых частых сценариев.
const error = new Error("Пользователь не найден");
Promise.reject(error).catch((reason) => {
console.log(reason.message); // "Пользователь не найден"
});
Это удобно, когда функция должна вернуть именно Promise, даже если ошибка уже известна заранее.
Если передать объект, он станет причиной отклонения как есть
Это важный нюанс.
const details = { code: 403, message: "Нет доступа" };
Promise.reject(details).catch((reason) => {
console.log(reason.code); // 403
});
Метод не преобразует это значение автоматически в Error.
В отличие от Promise.resolve(), Promise.reject() не принимает состояние промиса
Это один из самых важных моментов статьи.
Если передать в Promise.reject() уже существующий промис, он не будет “распакован”. Этот промис сам станет причиной отклонения.
const promise = Promise.resolve(5);
Promise.reject(promise).catch((reason) => {
console.log(reason === promise); // true
});
То есть здесь причиной ошибки будет сам объект промиса, а не его внутреннее значение.
То же правило работает и с thenable-объектами
Promise.reject() не пытается принять их состояние.
const thenable = {
then(resolve) {
resolve(42);
},
};
Promise.reject(thenable).catch((reason) => {
console.log(reason === thenable); // true
});
Это важное отличие от Promise.resolve(), который как раз пытается обработать thenable как источник состояния.
Promise.reject() не выбрасывает ошибку синхронно
Это полезно не путать с обычным throw.
const promise = Promise.reject(new Error("boom"));
console.log("Код продолжает выполняться");
Сам вызов Promise.reject() не прерывает текущую строку исполнения. Он только создаёт отклонённый промис.
Чтобы обработать причину ошибки, нужен catch() или второй аргумент then().
Чем Promise.reject() отличается от throw
Оба варианта связаны с ошибками, но работают по-разному.
throw new Error("boom");
throw сразу выбрасывает исключение в текущем синхронном коде.
Promise.reject(new Error("boom"));
Promise.reject() создаёт отклонённый промис, который потом должен быть обработан как часть promise-цепочки.
Если функция должна возвращать именно Promise, часто удобнее использовать Promise.reject().
Чем Promise.reject() отличается от new Promise(...)
Оба варианта могут создать отклонённый промис, но Promise.reject() обычно проще.
const promise1 = Promise.reject("boom");
const promise2 = new Promise((resolve, reject) => {
reject("boom");
});
Если нужно просто быстро вернуть ошибочный промис из уже известного значения, Promise.reject() обычно короче и понятнее.
Когда это полезно
Promise.reject() особенно удобен, когда:
- нужно быстро вернуть ошибочный промис
- функция всегда должна возвращать
Promise, даже при ранней ошибке - вы хотите начать цепочку сразу с ошибки
- нужно сохранить единый асинхронный интерфейс
Пример:
function getUser(id) {
if (!id) {
return Promise.reject(new Error("id обязателен"));
}
return fetch(`/api/users/${id}`)
.then((response) => response.json());
}
Такой подход помогает сделать формат возврата единым: в любом случае функция отдаёт Promise.
Частые ошибки
Думать, что Promise.reject() выбрасывает ошибку как throw
Promise.reject(new Error("boom"));
console.log("Этот код выполнится");
Promise.reject() не прерывает синхронное выполнение прямо в этой точке.
Ожидать синхронное выполнение catch()
console.log("A");
Promise.reject("boom").catch((reason) => {
console.log(reason);
});
console.log("B");
Сначала выведется A, потом B, и только потом boom.
Думать, что Promise.reject() обрабатывает переданный промис как Promise.resolve()
const promise = Promise.resolve(5);
Promise.reject(promise).catch((reason) => {
console.log(reason === promise); // true
});
Переданный промис становится причиной отклонения, а не источником значения.
Передавать строку вместо объекта Error, когда нужна нормальная ошибка
Promise.reject("Что-то пошло не так");
Так можно делать, но на практике чаще удобнее передавать new Error(...), потому что у него есть message и stack.
Думать, что Promise.reject() поймает синхронную ошибку в аргументе
Promise.reject(JSON.parse("{"))
.catch((error) => {
console.log(error);
});
Здесь JSON.parse("{") выбросит ошибку ещё до вызова Promise.reject(). Значит, такой catch() не поможет.
Создавать отклонённый промис и не обрабатывать его
Promise.reject(new Error("boom"));
Если такой промис оставить без catch(), можно получить предупреждение о необработанном отклонении.
Быстрая памятка
Promise.reject()вызывается уPromise- метод всегда возвращает объект
Promise - без аргументов причиной отклонения будет
undefined - переданное значение становится причиной отклонения как есть
Promise.reject()не делает код синхроннымcatch()после него всё равно выполняется асинхронно- переданный промис не “распаковывается”, а становится причиной ошибки
- thenable-объект тоже не принимается как источник состояния
- метод удобен, когда нужно вернуть ошибочный
Promiseс единым интерфейсом
Коротко
Promise.reject() в JavaScript нужен, чтобы быстро получить отклонённый промис из готовой причины ошибки. Главное, что стоит запомнить: метод всегда возвращает Promise, не выбрасывает исключение синхронно, не принимает состояние переданного промиса или thenable-объекта и особенно полезен там, где функция должна в любом случае возвращать promise-результат.