【问题标题】:Prevent a promise from triggering a global 'unhandled rejection' event防止 Promise 触发全局“未处理的拒绝”事件
【发布时间】:2016-02-05 17:06:22
【问题描述】:

我正在编写一个库。有一次,我创建了一个承诺,然后突然向其中添加 then/catch 处理程序。在我实际附加错误处理程序之前,承诺可能会失败。这对我来说很好;承诺可以以薛定谔猫的状态存在,直到我以后可能决定查看它。

问题是,如果 any 承诺在没有错误处理程序的情况下被拒绝,某些环境会触发全局事件。也许我的一位用户在 Node 中做了类似 this 之类的激烈操作:

process.on('unhandledRejection', function(reason){
    console.error('oops', reason);
    process.exit(1);
});

如果我知道我稍后会去检查它的结果,我不希望我被拒绝的承诺触发它。

是否有一些官方方法可以标记一个承诺以将其从任何全局“未处理拒绝”事件中排除,或者我是否真的必须将错误处理程序同步附加到每个承诺以避免这种情况?

【问题讨论】:

  • 并非所有环境都这样做,恕我直言,这样做的环境是错误的。只要您在某处持有对承诺的引用,环境就没有任何问题。
  • 对,但如果我希望我的库在 Node.js 中工作,我不能忽视现实。抛开现实不谈,如果一个被拒绝的承诺没有被抓住,应用程序想要大声退出是有正当理由的,以避免难以捉摸的错误,所以图书馆作者必须有一种方法来选择退出他们的内部承诺
  • 不与现实争论,但是在第二部分,我相信 Firefox 做了正确的事情:它只会在不再引用它们时才对被拒绝的未捕获的 Promise 大喊大叫。唯一的缺点是此报告目前需要几秒钟(可能会因垃圾收集而超时),但我相信他们正在努力。
  • 啊,这听起来确实是个好方法
  • 虽然从技术上讲,它会错过一些承诺仍然在某个范围内的情况,但是由于代码中的一些错误,您无法添加 catch 处理程序。在这种情况下,您会遇到“uncaughtRejection”事件旨在解决的错误吞咽问题。无论如何,Node 行为的现实,即使他们在未来的版本中改变它,也意味着库作者必须假设未捕获的拒绝可能会使某人的应用程序崩溃,无论我们是否认为这是一件好事。所以我想我们只需要解决它,并且永远不要让一个勾号以存在未处理的承诺而结束

标签: javascript promise


【解决方案1】:

在环境(节点)上提交错误。环境没有任何业务以脚本可观察的方式对其进行操作。

在 Firefox 和 Chrome 中,AFAIK 没有脚本可观察的后果。

尽管 Chrome 最初会在控制台中将其标记为“未处理的承诺拒绝”,并带有 ✖ 符号,并将其称为错误,但如果随后处理了承诺,它会后退,将 ✖ 更改为 ✓,并将其语言更改为“1 个已处理的承诺拒绝”。

只有在垃圾回收未处理的 Promise 拒绝时,Firefox 才会抱怨。

一种解决方法可能是添加一个hold 函数,例如:

var hold = p => (p.catch(() => {}), p);

然后,只要您知道以后会兑现承诺,就用它来使 Node 静音:

var console = { log: msg => div.innerHTML += msg + "<br>" };
window.onerror = () => console.log("window onerror fired");
var wait = ms => new Promise(resolve => setTimeout(resolve, ms));

var hold = p => (p.catch(() => {}), p);

var p = hold(Promise.reject(new Error("failure")));

wait(2000).then(() => p).catch(e => console.log(e.message + " handled."));
&lt;div id="div"&gt;&lt;/div&gt;

【讨论】:

  • hold 的想法很棒!超级简单,在这里实现我们想要的。酷!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-19
  • 1970-01-01
  • 1970-01-01
  • 2016-11-10
  • 2019-04-15
  • 1970-01-01
相关资源
最近更新 更多