Как обработать исключение, приводящее к нерешенному обещанию - PullRequest
0 голосов
/ 19 декабря 2018

Я наблюдаю некоторое непоследовательное поведение при работе с обещанием, которое не может быть выполнено из-за непредвиденного необработанного исключения.Кажется, что в зависимости от того, как цепочка обещаний меняется, решается ли это обещание, и я не понимаю, почему.

Вот плохая функция:

function bad() {
  return new Promise(resolve => {
    setTimeout(() => {
      throw 'unforseen exception!';
      resolve();
    }, 50);
  });
}

Если я вызываю эту функцию,способы, которые он не разрешает:

bad().then(() => console.log('resolved')); // no console logging

try {
  await bad();
} catch(e) {
  console.log(e);
}
console.log('resolved'); // no console logging

Но, если назвать его так, это решит:

Promise.resolve().then(bad()).then(() => console.log('resolved')); // console logs "resolved"

Почему это так? Редактировать: Теперь я понимаю, чем я былделаю неправильно.Но я действительно хочу ответить на следующую часть.

И как мне лучше защитить себя от непредвиденных исключений, когда у меня есть цепочка обещаний, которые должны выполняться последовательно и должны выполняться, даже если где-то в цепочке произошел сбой?

Я также пытался использовать catch или наконец, но они, кажется, не имеют никакого значения.Как только это неразрешенное обещание будет достигнуто, выполнение не будет выполнено.

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

В этом коде:

new Promise(resolve => {
  setTimeout(() => {
    throw 'unforseen exception!';
    resolve();
  }, 50);
});

Бросок происходит в не асинхронной функции обратного вызова.Чтобы справиться с чем-то подобным, можно использовать оператор try / catch для кода, который может выдавать:

new Promise((resolve, reject) => {
  setTimeout(() => {
    try {
      throw 'unforseen exception!';

      resolve();
    }
    catch (err) {
      reject(err);
    }
  }, 50);
});
0 голосов
/ 19 декабря 2018

Проблема в том, что bad() выдает ошибку асинхронно таким образом, что вызывающая сторона не может обнаружить ошибку.Если вы хотите выдать ошибку внутри сегмента new Promise..., вам следует вызвать функцию reject:

function bad() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject('bad!');
      resolve();
    }, 50);
  });
}


bad()
  .then(() => console.log('resolved'))
  .catch((err) => console.log(err));

(async () => {
  try {
    await bad();
  } catch(e) {
    console.log(e);
  }
  console.log('await finished');
})();

Причина, по которой ваши

Promise.resolve().then(bad()).then

вызывает следующий .then, заключается в том, что then принимает функцию в качестве параметра, но ваш bad() вызывает bad в начале , пока переводчик пытается придумать цепочку Обещаний.Если бы вы передали bad в качестве параметра функции вместо его вызова, вы бы увидели такое же нарушенное поведение, как в исходном коде - Promise никогда не разрешит:

function bad() {
  return new Promise(resolve => {
    setTimeout(() => {
      throw 'unforseen exception!';
      resolve();
    }, 50);
  });
}

// Promise never resolves:
Promise.resolve().then(bad).then(() => console.log('resolved'));

Напротив, .then(bad()) будет считаться неработоспособным, и, следовательно, .then разрешит немедленно , так что интерпретатор уйдетна следующий .then сразу же.

...