浏览器是否仍然默默地吞下未处理的被拒绝的承诺?Node怎么样?

Fli*_*imm 7 javascript node.js promise es6-promise

那里有很多建议,建议你确保你不要让任何被拒绝的承诺得不到处理.如果您不这样做,建议提醒,错误将永远不会被注意到,并且将被完全吞噬.没有任何东西会打印到控制台.

这个建议似乎已经过时了.现代浏览器和现代版本的Node似乎在被拒绝的承诺未处理时打印警告.拿这个代码:

async function thisIsGoingToFail() {
  await Promise.reject();
  console.log('this should not print, as the line above should error');
}

async function main() {
  await thisIsGoingToFail();
}

main();
Run Code Online (Sandbox Code Playgroud)

如果你在Node中运行它,你会得到:

(node:20760) UnhandledPromiseRejectionWarning: undefined
(node:20760) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:20760) [DEP0018] DeprecationWarning: 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.
Run Code Online (Sandbox Code Playgroud)

标准建议是源代码中的最后一行应该是这样的,以避免吞下错误:

main().catch(err => { console.err(err) });
Run Code Online (Sandbox Code Playgroud)

但它看起来并不像需要的那样.所以这是我的问题:

  • 现代浏览器和现代节点总是会对未处理的拒绝承诺发出警告吗?哪些版本的实现支持这个?
    • (请注意,浏览器不必支持事件unhandledrejection,以便在未处理承诺时打印警告.)
  • 我们是否需要确保catch按照您经常建议的方式执行顶级功能,或者让实现显示警告同样有用吗?

Fli*_*imm 5

大多数未实现的诺言未处理拒绝的承诺时,大多数现代实现都会向控制台打印警告,但并非全部:

  • ?从6.6.0版开始的Node.js(请参阅changelog):

    承诺:未处理的拒绝现在在第一个滴答声之后发出过程警告。(本杰明·格伦鲍姆)#8223

    在将来的版本中,未处理的承诺拒绝将以非零退出代码终止Node.js进程。

  • Firefox确实显示了警告,但是我找不到哪个是第一个执行此操作的版本。MDN文档说:

    我们采用以下策略:如果某个承诺在其垃圾回收时被拒绝,并且该承诺位于承诺链的末尾(即从未被调用那那Promise.then),那么我们将打印警告。

    注意:此警告是在错误发生后的某个时间生成的,并且可能提供的有关错误位置的信息较少。它通常表明需要插入适当的错误处理程序。当使用适当的拒绝处理程序时,它将有效地替换此延迟的报告。

  • Chrome浏览器确实显示了警告,但我仍然找不到说明哪个版本的文档。Chrome> = 49更进一步,并且支持unhandledrejectionevent,它使您可以添加自定义事件处理程序来处理所有未处理的拒绝诺言。

  • Safari也显示警告,并且由于版本> = 11,因此也支持该unhandledrejection事件。

  • ?根据Microsoft / ChakraCore中的这个GitHub公开问题,Edge似乎还不支持它。

因此,看起来大多数现代浏览器(Edge除外)的确会显示针对未处理的拒绝的警告,但是没有明确的文档来保证将显示警告或将其立即显示。unhandledrejection对于支持该事件的浏览器来说,处理该事件似乎是个好主意。


tldr; 在撰写本文时,似乎最佳实践似乎仍然是使用顶级拒绝诺言处理程序catch(以避免Edge中的误吞错误以及Node中终止的进程)。对于Chrome和Safari,利用unhandledrejected事件可能会很有用。