当前位置: 首页 > 面试题库 >

我应该避免异步处理Promise拒绝吗?

曹华荣
2023-03-14
问题内容

我刚刚安装了Node v7.2.0,并了解了以下代码:

var prm = Promise.reject(new Error('fail'));

结果消息:

(node:4786) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: fail
(node:4786) 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.

我理解这背后的原因,因为许多程序员可能经历了Error最终被吞噬的沮丧Promise。但是然后我做了这个实验:

var prm = Promise.reject(new Error('fail'));

setTimeout(() => {
    prm.catch((err) => {
        console.log(err.message);
    })
},
0)

结果是:

(node:4860) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: fail
(node:4860) 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.
(node:4860) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
fail

我基于 异步PromiseRejectionHandledWarning处理Promise拒绝的 想法 /可能是一件坏事。

但是为什么呢?


问题答案:

“我应该避免异步处理Promise拒绝吗?”

这些警告起着重要的作用,但要查看其工作原理,请参见以下示例:

尝试这个:

process.on('unhandledRejection', () => {});
process.on('rejectionHandled', () => {});

var prm = Promise.reject(new Error('fail'));

setTimeout(() => {
    prm.catch((err) => {
        console.log(err.message);
    })
}, 0);

或这个:

var prm = Promise.reject(new Error('fail'));
prm.catch(() => {});

setTimeout(() => {
    prm.catch((err) => {
        console.log(err.message);
    })
}, 0);

或这个:

var var caught = require('caught');
var prm = caught(Promise.reject(new Error('fail')));

setTimeout(() => {
    prm.catch((err) => {
        console.log(err.message);
    })
}, 0);

免责声明:我是catch模块的作者(是的,我为这个答案写的)。

基本原理

它已作为v6和v7之间的重大更改之一添加到Node中。在问题#830进行了激烈的讨论:默认未处理的拒绝检测行为并且没有关于异步连接拒绝处理程序的promise的行为应如何行为的普遍性共识-在没有警告的情况下工作,在没有警告的情况下工作,或者通过终止程序完全禁止使用。在未处理拒绝规范项目的几个问题上进行了更多讨论

此警告是为了帮助您找到忘记处理拒绝的情况,但有时您可能希望避免这种情况。例如,您可能要发出一堆请求并将结果的promise存储在数组中,以便稍后在程序的其他部分进行处理。

相对于回调,promise的优点之一是您可以将创建Promise的位置与附加处理程序的位置分开。这些警告使执行起来更加困难,但是您可以处理事件(我的第一个示例),也可以在创建不想立即处理的承诺的任何地方附加虚拟捕获处理程序(第二个示例)。或者,您可以让一个模块为您完成(第三个示例)。

避免警告

如果分两个步骤执行,则附加空处理程序不会改变存储的promise的工作方式:

var prm1 = Promise.reject(new Error('fail'));
prm1.catch(() => {});

但是,这将是不同的:

var prm2 = Promise.reject(new Error('fail')).catch(() => {});

prm2将是一个不同的承诺prm1。虽然prm1将被拒绝并显示“失败”错误,但prm2将解决undefined您可能不需要的错误。

但是您可以编写一个简单的函数,使其像上面的两步示例一样工作,就像我对caught模块所做的那样:

var prm3 = caught(Promise.reject(new Error('fail')));

prm3与相同prm1

2017更新

另请参见请求请求#6375:lib,src:对标记为Milestone8.0.0的未处理的承诺拒绝(自2017年2月起尚未合并)“抛出”:

做出承诺“抛出”拒绝,这些拒绝 像常规的未捕获错误一样退出[重点添加]

这意味着我们可以期望Node 8.x将此问题的警告更改为崩溃并终止进程错误,并且在今天编写我们的程序时应该考虑到这一点,以避免将来出现意外情况。



 类似资料:
  • 所以我迁移我的量角器测试使用异步/等待(链接)。 到目前为止,迁移是比较成功的,直到我一直遇到这个问题。下面是我的测试步骤,然后是代码,作为我正在处理的示例: 导航到特定页面 上述步骤的相关代码: 测验ts 我一直得到这个错误: (节点: 13672)UnhandledPromiseRejse警告:未处理的promise拒绝(拒绝id: 1): StaleElementRequiceError:

  • 我得到这个错误- (节点:18420)未处理的PromisejectionWarning:TypeError:无法读取未定义的属性“name” (节点:18420)未处理的PromisejectionWarning:未处理的promise拒绝。此错误源于在没有catch块的情况下抛出异步函数的内部,或者拒绝使用未处理的promise。catch()。要在未处理的promise拒绝时终止节点进程,请

  • 我想在Repl上为我的游戏实现一个基本的排行榜。它,所以我创建了一个节点。js后端。这是我在后端的配置: 但是每当我尝试发布时,我都会得到以下错误: (节点:344)未处理的PromisejectionWarning:TypeError:无法读取null的属性“push” (节点:344)UnhandledPromiseRejtionWarning:未处理的promise拒绝。这个错误要么是由于抛

  • 我有以下验证函数检查用户是否存在: 以下使用Chai的测试应对此进行测试: 错误确实会被抛出,但是mocha在控制台中显示以下内容: 2)显示抛出,如果用户是未定义的(节点: 18587)UnhandledPromiseRejse警告:未处理的promise拒绝(拒绝id: 2):错误:用户不存在 所以我的问题是,我如何重写测试,让它捕捉到promise拒绝?

  • 我正在与节点JS中的promise模式作斗争 我在db中寻找用户,然后用用户引用保存新实体,但当用户不在db中时,我应该返回拒绝,但我不确定如何正确地做到这一点。 有什么办法可以做得更好吗? btw:对不起,coffeescript :-[

  • 本文介绍了单个promise组合器: 但我没有看到的是,一种运行所有promise的方法,但不是在个人promise被拒绝时短路。我如何确保所有的promise都得到履行,但我能处理拒绝和所有promise的解决?