62

一旦调用了 promisereject()回调,Chrome 控制台中就会出现警告消息“Uncaught (in promise)” 。我无法理解背后的原因,也无法摆脱它。

var p = new Promise((resolve, reject) => {
  setTimeout(() => {
    var isItFulfilled = false
    isItFulfilled ? resolve('!Resolved') : reject('!Rejected')
  }, 1000)  
})

p.then(result => console.log(result))
p.catch(error => console.log(error))

警告:

在此处输入图像描述

编辑:

我发现如果onRejected处理程序没有显式提供给.then(onResolved, onRejected)方法,JS 会自动提供一个隐式处理程序。它看起来像这样:(err) => throw err。自动生成的处理程序将轮流抛出。

参考:

如果 IsCallable( onRejected )` 为false,则
     令onRejected为“ Thrower ”。

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-performpromisethen

4

4 回答 4

57

发生这种情况是因为您没有将 catch 处理程序附加到第一个then方法返回的承诺,因此当承诺拒绝时没有处理程序。最后一行的 promise确实有一个,但在它之前的行中,方法返回的链式promise没有。pthen

正如您在下面的评论中正确添加的那样,当未提供 catch 处理程序(或它不是函数)时,默认处理程序将引发错误。在 Promise 链中,可以通过方法回调捕获此错误catch,但如果没有,JavaScript 引擎将像处理任何其他未捕获的错误一样处理该错误,并在这种情况下应用默认处理程序,这会导致您在控制台中看到的输出。

为避免这种情况,请将.catch方法链接到 first 返回的承诺then,如下所示:

p.then( result =>  console.log('Fulfilled'))
 .catch( error =>  console.log(error) );
于 2017-02-25T18:40:22.300 回答
1

即使您正确使用 Promises:p.then(p1).catch(p2)如果您的 p2 函数最终抛出您打算使用诸如 window.onerror 之类的机制捕获的异常,您仍然可以获得未捕获的异常。原因是堆栈已经被 promise 中的错误处理解开。要解决此问题,请确保您的错误代码(由拒绝函数调用)不会引发异常。它应该简单地返回。

如果错误处理代码可以检测到堆栈已经被解开,那就太好了(所以你的错误调用不必有这种情况的标志),如果有人知道如何轻松地做到这一点,我将编辑这个答案包括那个解释。

于 2019-08-26T13:09:48.623 回答
0

此代码不会导致“未捕获的承诺”异常:

// Called from top level code; 
// implicitly returns a Promise
testRejectCatch = async function() {

    // Nested within testRejectCatch;
    // simply rejects immediately
    let testReject = function() {
        return new Promise(function(resolve, reject) {
            reject('test the reject');
        )};
    }
 
//***********************************************
// testRejectCatch entry.
//***********************************************
try {
    await testReject(); // implicitly throws reject exception
catch(error) {
    // somecode 
 }

//***********************************************
// top level code
//***********************************************
try{
    testRejectCatch()   // Promise implicitly returned,
    .catch((error) => { // so we can catch
        window.alert('Report error: ' + error);
       // must not throw error;
    });
}
catch(error) {
    // some code
}

解释:首先,有一个术语问题。术语“catch”以两种方式使用:在 try-catch 中和在 Promise 中。因此,很容易对“投掷”感到困惑;它是投掷到try's catch还是Promise's catch?

答:testReject 中的reject 是抛给Promise 的隐式catch,在await testReject;然后在 testRejectCatch() 处抛出 .catch。

在这种情况下,try-catch 是无关紧要的,被忽略了;投掷与他们无关。

testRejectCatch 处的 .catch 满足原始 throw 必须在某处捕获的要求,因此您不会遭受“在 Promise 中未捕获...”异常。

要点:Promises 的 throws 是 throws 到 .catch,而不是 try-catch;并且必须在某些 .catch 中处理

编辑:在上面的代码中,拒绝通过 .catch 向上传播。如果你愿意,你可以转换为传播 try-catch。在第 17 行,将代码更改为:

let bad = '';
await testReject().catch((error) => {bad = error});
if (bad) throw bad;

现在,您已切换到 try-catch。

于 2021-07-26T17:15:15.227 回答
-3

我已经在我的项目中解决了这个问题,这是一个大型企业。我的团队懒得写空catch几百遍了。

Promise.prototype.then = function (onFulfilled, onRejected) {
    return baseThen.call(this, (x: any) => {
        if (onFulfilled)
            onFulfilled(x);
    }, (x: any) => {
        if (onRejected)
            onRejected(x);
    });
};
于 2020-05-14T15:23:51.593 回答