浏览器是否仍然默默地吞下未处理的被拒绝的承诺?节点呢?

问题描述 投票:0回答:1

有很多建议建议您确保不要让任何被拒绝的承诺得不到处理。建议警告说,如果不这样做,错误将永远不会被注意到,并且将被完全吞没。控制台不会打印任何内容。

这个建议似乎已经过时了。当被拒绝的承诺未被处理时,现代浏览器和现代版本的 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();

如果你在 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.

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

main().catch(err => { console.err(err) });

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

  • 现代浏览器和现代 Node 是否总是会针对未处理的被拒绝的 Promise 显示警告?哪些版本号的实现支持此功能?
    • (请注意,浏览器不必支持事件
      unhandledrejection
      才能在未处理承诺时打印警告。)
  • 我们是否需要确保拥有顶级
    catch
    功能,就像您经常建议的那样,还是让实现显示警告同样有用?
javascript node.js promise es6-promise
1个回答
6
投票

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

  • Node.js 自版本 6.6.0 起(参见 变更日志):

    承诺:未处理的拒绝现在会在第一次勾选后发出流程警告。 (本杰明·格伦鲍姆)#8223

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

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

    我们采用以下策略:如果 Promise 在垃圾收集时被拒绝 并且如果 Promise 位于 Promise 链的末尾(即从未调用过 thatPromise.then),那么我们会打印一条警告.

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

  • Chrome 确实显示了警告,但我再次找不到表明哪个版本是执行此操作的第一个版本的文档。 Chrome >= 49 更进一步,支持

    unhandledrejection
    事件,它允许您添加自定义事件处理程序来处理所有未处理的拒绝承诺。

  • Safari 也会显示警告,并且从版本 >= 11 开始,还支持

    unhandledrejection
    事件。

  • Edge 似乎从 Chakracore 1.10 开始支持它,基于 Microsoft/ChakraCore 中的 GitHub 问题

所以看起来大多数现代浏览器(Edge 除外)确实会显示未处理拒绝的警告,但没有明确的文档保证会显示警告,或者会立即显示。对于支持它的浏览器来说,处理

unhandledrejection
事件似乎是个好主意。


tldr; 截至撰写本文时,最佳实践似乎仍然是使用

catch
保留顶级拒绝的 Promise 处理程序(以避免 Edge 中的吞没错误和 Node 中的终止进程)。对于 Chrome 和 Safari,利用
unhandledrejected
事件可能很有用。

© www.soinside.com 2019 - 2024. All rights reserved.