Javascript 为什么是;未经处理的拒绝承诺”;一件事?

Javascript 为什么是;未经处理的拒绝承诺”;一件事?,javascript,asynchronous,promise,Javascript,Asynchronous,Promise,我了解何时发生未处理的PromisejectionWarning错误。 我不明白的是,为什么规范的编写方式允许这种行为 例如,以下代码是错误的,如果callApi()拒绝,则节点中会出现未处理PromisejectionWarning错误,每个浏览器中都会出现类似错误: class A { constructor () { this._stuff = Promise.reject(Error('oops')) } getStuff () {

我了解何时发生
未处理的PromisejectionWarning
错误。 我不明白的是,为什么规范的编写方式允许这种行为

例如,以下代码是错误的,如果
callApi()
拒绝,则节点中会出现
未处理PromisejectionWarning
错误,每个浏览器中都会出现类似错误:

class A {
    constructor () {
        this._stuff = Promise.reject(Error('oops'))
    }
    getStuff () {
        return this._stuff
    }
}

const a = new A()

setTimeout(() => {
    a.getStuff().catch(err => console.log('I caught it!'))
}, 100)
但为什么?!我倾向于把承诺看作是当事情发生时的抽象。 如果
callApi()
成功,这正是承诺的作用:当数据可用时,
getStuff()
的调用者将获得数据


但是拒绝案例的工作方式不同。我期望发生的事情(如果我以前没有被这件事烧坏的话)是处理错误的负担落在
getStuff
的调用者身上。这不是它的工作原理,而是原因?

在node.js中,检测未处理的承诺拒绝是不完美的。我不知道它在内部是如何工作的,但是如果在承诺链中没有
.catch()
,并且该承诺被拒绝,即使您将其分配给一个变量,然后再向其添加
.catch()
,它也会给您“未处理的拒绝警告”

在您的特定情况下,这可能是因为您返回到事件循环时没有捕获到一个被拒绝的承诺—您的
.catch()
只是稍后在后续事件中添加的。node.js解释器无法知道您将要这样做。它会看到一个事件已完成执行,并且拒绝的承诺未得到处理,因此会创建警告

为了避免警告,您必须以不同的方式对其进行编码。你并没有真正展示真实世界的用途,所以我们可以看到你试图完成什么来提出具体的建议。与其他类型的事情一样,处理它的最佳方式取决于现实世界的用例



如果你问为什么一个未经处理的拒绝是一个警告,那是因为它可能是一个严重的错误,如果没有警告,那么它只会默默地失败,开发人员将永远不会更明智。它非常类似于同步代码中未处理的异常。这是一个严重错误,会中止程序。node.js已经通知了一段时间,未经处理的拒绝可能在将来得到相同的处理。现在,这只是一个警告。

我不确定我是否完全理解您的需要。如果
getStuff
成功,那么
getStuff()
上的
回调将启动,如果失败,则启动
.catch
。拒绝案例与成功案例有何不同?为什么投票被否决?@JohanP我希望getStuff()的调用方能够收到拒绝,并且不会出现未经处理的承诺拒绝错误。谢谢你的回答,但我一直在问为什么会这样。我理解这个错误。@MaxHeiber-因为未经处理的拒绝很像同步代码中未经处理的异常。这是一个严重的错误,不应该在没有人知道它发生的情况下默默地失败。@MaxHeiber-你可能想澄清你的问题。上面写着“但是为什么?”,但不清楚你到底在问什么。我以为您在问“当我添加
.catch()
”时,为什么此代码会遭到未经处理的拒绝?”?如果你想问一些不同的问题,那么请编辑你的问题来澄清。我在措辞上有点纠结。我提出了“我理解什么时候发生了未经处理的PromisejectionWarning错误。我不理解的是为什么规范的编写方式允许这种行为。”我如何才能更清楚地说明这一点?@MaxHeiber-下面是关于该功能的讨论:该功能将演变为以下内容:它描述了中实现的更多细节