Promise reject()导致“Uncaught(in promise)”​​警告

时间:2017-02-25 18:35:33

标签: javascript promise es6-promise catch-block

调用promise reject()回调后,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))

警告:

enter image description here

修改

我发现如果没有向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 个答案:

答案 0 :(得分:22)

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

正如您在下面的评论中正确添加的那样,当未提供catch处理程序(或它不是函数)时,default one will throw错误。在promise链中,可以使用catch方法回调来捕获此错误,但如果没有,则JavaScript引擎将像处理任何其他未捕获的错误一样处理错误,并在此类中应用默认处理程序环境,导致您在控制台中看到的输出。

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

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

答案 1 :(得分:0)

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

如果错误处理代码可以检测到堆栈已经解开(这对于您的错误调用不必具有这种情况的标记),那将很好,并且如果有人知道如何轻松地执行此操作,我会编辑此答案以包含该说明。

答案 2 :(得分:0)

这段代码不会导致“uncaught in promise”异常:

// 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
}

说明: 首先,有一个术语问题。 “捕获”一词是 以两种方式使用:在 try-catch 中和在 Promises 中。 因此,很容易对“抛出”感到困惑;是扔吗 是 try 的捕获还是 Promise 的捕获?

答案:testReject 中的 reject 是扔给 Promise 的 隐式捕获,在 await testReject;然后扔到 testRejectCatch() 中的 .catch。

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

testRejectCatch 处的 .catch 满足要求 原始投掷必须在某处被捕获, 所以你不会遭受“未捕获的承诺......”例外。

要点:Promises 的 throws 是 throws 到 .catch, 不要尝试捕捉;并且必须在某些 .catch 中处理

编辑: 在上面的代码中,拒绝通过 .catch 向上传播。 如果需要,您可以转换为传播尝试捕获。 在第 17 行,将代码更改为:

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

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

答案 3 :(得分:-3)

我已经在我的项目中解决了这个问题,这是一个大型企业。我的团队太懒了,无法写数百次空捕获。

Promise.prototype.then = function (onFulfilled, onRejected) {
    return baseThen.call(this, (x: any) => {
        if (onFulfilled)
            onFulfilled(x);
    }, (x: any) => {
        if (onRejected)
            onRejected(x);
    });
};