Почему родительское обещание не перехватило бы отклонение вложенного обещания?

#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');
  

Вы:

  1. Вызовите reject() функцию для Promise объекта.
  2. Отбросьте результат.

Даже если здесь создается (отклоняющее) обещание, вы ничего не делаете с результатом. Это точно так же, как вызвать функцию, но затем ничего не делать с тем, что было 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) => {}) , это произойдет немедленно, остановите выполнение кода и начнется обработка ошибок. Обещание неявно улавливает эту ошибку внутри, и ее состояние отклоняется.