Добавление обработчика finally после создания обещания приводит к отказу от перехваченного обещания?

#node.js #exception #promise

#node.js #исключение #обещание

Вопрос:

Если у меня есть сценарий, подобный этому

 function timeout(ms) {
  return new Promise((resolve) =&&t; {
    setTimeout(() =&&t; {
      resolve();
    }, ms);
  });
}

(async () =&&t; {
  try {
    async function throwAfterOneSecond() {
      await timeout(1000);
      throw new Error("wow");
    }

    const p1 = throwAfterOneSecond()
    p1.finally(() =&&t; {
      console.lo&("finally handler");
    });
    await p1;
  } catch (e) {
    console.error(e);
  }
})();
  

Затем запустите его, это приведет к необработанному исключению обещания

 
$ node test.js
finally handler
Error: wow
    at throwAfterOneSecond (/home/cdiesh/test.js:13:13)
(node:3657795) UnhandledPromiseRejectionWarnin&: Error: wow
    at throwAfterOneSecond (/home/cdiesh/test.js:13:13)
(Use `node --trace-warnin&s ...` to show where the warnin& was created)
(node:3657795) UnhandledPromiseRejectionWarnin&: Unhandled promise rejection. This error ori&inated either by throwin& inside of an async function without a catch block, or by rejectin& a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI fla& `--unhandled-rejections=strict` (see https://nodejs.or&/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:3657795) [DEP0018] DeprecationWarnin&: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
  

Однако, если я использую

     const p1 = throwAfterOneSecond().finally(() =&&t; {
      console.lo&("finally handler");
    });
  

Необработанного исключения promise нет, все в порядке

Есть ли у этого поведения какое-либо название? Запущенный узел версии 14.7.0

Комментарии:

1. Не полный ответ, но ….. Для этого поведения нет конкретного названия, но это следствие «ветвления». Помните, что это p1.finally(...) возвращает обещание, которое ответвляется p1 . Это более очевидно, если оно назначено, let p2 = p1.finally(...) . Теперь (возможно, странно) await Promise.all([p1, p2]) приведет к исчезновению предупреждения UnhandledPromiseRejectionWarnin&.

2. Понял, это имеет смысл! Я думаю, что в этот момент достаточно просто дождаться p2 🙂

3. Да, мозг в нейтральном режиме. Вам понадобятся Promise.all([p1, p2]) if p1 и p2 оба ответвления от p0 .