#javascript #node.js #promise #es6-promise
#javascript #node.js #обещание #es6-promise
Вопрос:
Почему вложенное отклоненное обещание не было бы перехвачено родительским обещанием? Но, если я выполню «бросок» внутри родительского обещания, оно будет поймано.
var parent = new Promise((res, rej) => {
// this DOES NOT get caught by the parent.
Promise.reject("A plain reject");
// this gets caught by the parent
// throw new Error("Arbitrary error");
});
parent.catch(err => {
console.log("parent catches the error");
});
Обновление: я не пытаюсь переписать это, где родительское обещание перехватывается отклоненным. Я просто хочу понять «почему»? Спасибо!
Комментарии:
1. Я думаю, вам следует просто вызвать reject («что-то»), а не присоединять reject к глобальному объекту Promise.
Ответ №1:
Вы не отклоняете родительское, вы просто создали новое вложенное отклоненное обещание, а затем немедленно его отбросили.
Вот как вы можете переписать это:
const parent = new Promise((res, rej) => {
// nested reject
Promise.reject("A plain reject").then(res, rej);
});
Это все еще плохой шаблон. Вы действительно должны попытаться избежать new Promise
, если сможете. Немного сложно действительно рассказать вам, как правильно это написать, не видя более реалистичного примера, потому что вышеописанное можно переписать как:
const parent = Promise.reject("A plain reject");
Отредактируйте ответ на ваше последующее действие:
Обновление: я не пытаюсь переписать это, где родительское обещание перехватывается отклоненным. Я просто хочу понять «почему»? Спасибо!
Когда вы throw
создаете исключение, это языковая функция, которая останавливает текущую функцию и создает исключение до тех пор, пока что-то в стеке вызовов не получит catch
.
Когда вы пишете оператор типа:
Promise.reject('foo');
Вы:
- Вызовите
reject()
функцию дляPromise
объекта. - Отбросьте результат.
Даже если здесь создается (отклоняющее) обещание, вы ничего не делаете с результатом. Это точно так же, как вызвать функцию, но затем ничего не делать с тем, что было returned
, и задаваться вопросом, куда делся результат.
Итак, ваш первоначальный пример:
var parent = new Promise((res, rej) => {
// this DOES NOT get caught by the parent.
Promise.reject("A plain reject");
// this gets caught by the parent
// throw new Error("Arbitrary error");
});
фактически это то же самое, что:
var parent = new Promise((res, rej) => {
// this DOES NOT get caught by the parent.
true;
});
или
var parent = new Promise((res, rej) => {
// this DOES NOT get caught by the parent.
5;
});
или
var parent = new Promise((res, rej) => {
// this DOES NOT get caught by the parent.
"hello".indexOf('h');
});
Строка выполняется, но она «бессмысленна», потому что у нее нет побочных эффектов.
Комментарии:
1. Спасибо за быстрый ответ. Код, который я опубликовал, предназначен для изолированной обработки / обучения для понимания обещаний. Я знаю, что есть разные способы записать это. Я просто хочу понять, почему такое поведение.
Ответ №2:
У вас есть функция отклонения, rej
, переданная в обратный вызов promise. Вы должны использовать это, чтобы отклонить обещание, а не создавать новое отклоненное обещание. Вот для чего это нужно:
var parent = new Promise((res, rej) => {
// nested reject
rej("A plain reject");
});
parent.catch(err => {
console.log("parent catches the error: ", err);
});
Если по какой-то причине у вас уже есть отклоненное обещание, вы можете разрешить его, что также приведет к срабатыванию catch, хотя это кажется странной ситуацией:
var parent = new Promise((res, rej) => {
// nested reject
res(Promise.reject("A plain reject"));
});
parent.catch(err => {
console.log("parent catches the error", err);
});
Комментарии:
1. Спасибо за быстрый ответ. Код, который я опубликовал, предназначен для изолированной обработки / обучения для понимания обещаний. Я знаю, что есть разные способы записать это. Я просто хочу понять, почему такое поведение.
Ответ №3:
Promise.reject("A plain reject")
возвращает обещание, состояние которого отклонено, то есть это просто обычный объект, а не выданная ошибка.
Но вы ничего не делаете с обещанием, которое возвращается из Promise.reject("A plain reject")
. И из-за этого обещание, созданное new Promise((res, rej) => {})
, никак не может знать, в каком состоянии находится это обещание (например, что оно было отклонено), и даже если бы оно знало состояние, оно не знало бы, что оно должно что-то делать с этим обещанием. Возможно, вы захотите сделать что-то еще с обещанием.
С другой стороны, если вы throw
обнаружите ошибку внутри new Promise((res, rej) => {})
, это произойдет немедленно, остановите выполнение кода и начнется обработка ошибок. Обещание неявно улавливает эту ошибку внутри, и ее состояние отклоняется.