为啥延迟处理承诺拒绝有时会导致 UnhandledPromiseRejectionWarning?

Posted

技术标签:

【中文标题】为啥延迟处理承诺拒绝有时会导致 UnhandledPromiseRejectionWarning?【英文标题】:Why does delaying handling of promise rejections sometimes result in UnhandledPromiseRejectionWarning?为什么延迟处理承诺拒绝有时会导致 UnhandledPromiseRejectionWarning? 【发布时间】:2021-07-30 06:24:08 【问题描述】:

当我运行以下代码时,为什么会收到未处理的 Promise 拒绝警告?

async function load() 
  throw new Error('error');


async function main() 
  const promise = load();

  await new Promise(resolve => setTimeout(resolve, 5000));

  try 
    await promise;
   catch (e) 
    console.log('caught error', e);
  


main();

这是输出:

jkim@dev-jkim test $ node index.js
(node:25276) UnhandledPromiseRejectionWarning: Error: error

由于await promise 是一个try-catch,我很困惑为什么我的try-catch 没有捕捉到错误。我想这与setTimeout 有关,因为以下代码有效:

async function load() 
  throw new Error('error');


async function main() 
  const promise = load();
  try 
    await promise;
   catch (e) 
    console.log('caught error', e);
  


main();
jkim@dev-jkim test $ node index.js
caught error Error: error

这里发生了什么?如果在当前刻度结束时未处理承诺拒绝,是否会自动导致未处理的承诺拒绝警告?

(我在节点 v10.16.3 上)

【问题讨论】:

【参考方案1】:

函数load() 抛出一个Error。如果在处理Promise 时出现错误thrown,则Promise 被拒绝。现在,如果错误 load() 没有被捕获,那么 JS 会抛出 UnhandledPromiseRejectionWarning

您的代码的更好说明是:

function load() 
    console.log("hello after some time");


const foo = new Promise((resolve, reject) => 
    setTimeout(resolve, 5000);
)
.then(() =>  load(); )
.catch((e) =>  console.log(`Caught Error: $e`));

【讨论】:

【参考方案2】:

如果在当前刻度结束时未处理承诺拒绝,是否会自动导致未处理的承诺拒绝警告?

是的。 Promise 必须在它被拒绝时附加一个拒绝处理程序,否则拒绝将被视为未处理。如果您稍后附加拒绝处理程序,例如在

await new Promise(resolve => setTimeout(resolve, 5000));

当解释器到达时,load Promise 已被拒绝

try 
  await promise;
 catch (e) 

所以,虽然可以用.catch 捕获拒绝,但它没有被任何东西在拒绝的那一刻捕获,从而导致警告。

此类事情的最佳实践是始终立即附加拒绝处理程序 - 无论这意味着 .catch,还是在 try/catchPromise.all 内,或者为调用者返回 Promise处理。

【讨论】:

以上是关于为啥延迟处理承诺拒绝有时会导致 UnhandledPromiseRejectionWarning?的主要内容,如果未能解决你的问题,请参考以下文章

为啥修改项目输出目录会导致:IOException is unhandled “Cannot locate resource 'app.xaml'.”

设置firebase时出错,可能会出现未处理的承诺拒绝

等待但从未解决/拒绝承诺内存使用[重复]

链式承诺不会在拒绝时传递

处理多个承诺拒绝[重复]

条纹元素抛出“未处理的承诺拒绝”