浏览器是否仍然默默地吞并未处理的拒绝承诺?那Node呢?

时间:2018-08-28 15:22:22

标签: 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();

如果在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会始终对未处理的拒绝诺言显示警告吗?实现的哪些版本号支持此功能?
    • (请注意,浏览器不必支持事件unhandledrejection即可在未处理承诺时打印警告。)
  • 我们是否需要确保像您经常建议的那样具有顶级catch功能,还是让实现显示警告同样有用?

1 个答案:

答案 0 :(得分:3)

大多数未实现的诺言未处理被拒绝的诺言时,大多数现代实现都会向控制台打印警告,

  • Node.js 自版本6.6.0起(请参见changelog):

      

    承诺:现在,在第一次滴答之后,未处理的拒绝会发出过程警告。 (Benjamin Gruenbaum)#8223

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

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

      

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

         
        

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

      
  • Chrome 确实显示警告,但是我再也找不到说明哪个是第一个版本的文档。 Chrome> = 49更进一步,并支持unhandledrejection event,可让您添加自定义事件处理程序来处理所有未处理的拒绝承诺。

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

  • 基于此open GitHub issue in Microsoft/ChakraCore
  • Edge 似乎还不支持它。

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


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