Javascript 承诺拒绝()导致“未捕获(承诺)”警告
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42460039/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Promise reject() causes "Uncaught (in promise)" warning
提问by Yevgeny Kozlov
Once a promise reject()callback is called, a warning message "Uncaught (in promise)"appears in the Chrome console. I can't wrap my head around the reason behind it, nor how to get rid of it.
一旦reject()调用了 promise回调,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))
Warning:
警告:


Edit:
编辑:
I found out that if the onRejectedhandler is not explicitly provided to the .then(onResolved, onRejected)method, JS will automatically provide an implicit one. It looks like this: (err) => throw err. The auto generated handler will throw in its turn.
我发现如果onRejected处理程序没有显式提供给.then(onResolved, onRejected)方法,JS 会自动提供一个隐式的。它看起来像这样:(err) => throw err。自动生成的处理程序将依次抛出。
Reference:
参考:
If IsCallable(onRejected)` is false, then
Let onRejectedbe "Thrower".
如果 IsCallable( onRejected)` 为false,则
让onRejected为“ Thrower”。
http://www.ecma-international.org/ecma-262/6.0/index.html#sec-performpromisethen
http://www.ecma-international.org/ecma-262/6.0/index.html#sec-performpromisethen
采纳答案by trincot
This happens because you do not attach a catch handler to the promise returned by the first thenmethod, which therefore is without handler for when the promise rejects. You dohave one for the promise pin the last line, but not for the chainedpromise, returned by the thenmethod, in the line before it.
发生这种情况是因为您没有将 catch 处理程序附加到第一个then方法返回的承诺,因此当承诺拒绝时没有处理程序。您确实有一个用于p最后一行中的承诺,但没有用于方法返回的链接承诺,then在它之前的行中。
As you correctly added in comments below, when a catch handler is not provided (or it's not a function), the default one will throwthe error. Within a promise chain this error can be caught down the line with a catchmethod callback, but if none is there, the JavaScript engine will deal with the error like with any other uncaught error, and apply the default handler in such circumstances, which results in the output you see in the console.
正如您在下面的评论中正确添加的那样,当未提供 catch 处理程序(或它不是函数)时,默认处理程序将抛出错误。在 promise 链中,这个错误可以通过catch方法回调被捕获,但如果没有,JavaScript 引擎将像处理任何其他未捕获的错误一样处理该错误,并在这种情况下应用默认处理程序,从而导致您在控制台中看到的输出。
To avoid this, chain the .catchmethod to the promise returned by the first then, like this:
为避免这种情况,将.catch方法链接到 first 返回的承诺then,如下所示:
p.then( result => console.log('Fulfilled'))
.catch( error => console.log(error) );
回答by David Spector
Even if you use Promises correctly: p.then(p1).catch(p2)you can still get an uncaught exception if your p2 function eventually throws an exception which you intend to catch using a mechanism like window.onerror. The reason is that the stack has already been unwound by the error handling done in the promise. To fix this, make sure that your error code (called by the reject function) does not throw an exception. It should simply return.
即使您正确使用了 Promise:p.then(p1).catch(p2)如果您的 p2 函数最终抛出一个您打算使用 window.onerror 之类的机制捕获的异常,您仍然会得到一个未捕获的异常。原因是堆栈已经被 Promise 中的错误处理解开。要解决此问题,请确保您的错误代码(由拒绝函数调用)不会引发异常。它应该简单地返回。
It would be nice if the error handling code could detect that the stack has already been unwound (so your error call doesn't have to have a flag for this case), and if anyone knows how to do this easily I will edit this answer to include that explanation.
如果错误处理代码可以检测到堆栈已经展开(因此您的错误调用不必为这种情况提供标志),那将会很好,如果有人知道如何轻松做到这一点,我将编辑此答案包括那个解释。
回答by stbear
I've solved that problem in my project, it's a large enterprise one. My team is too lazy to write empty catch hundreds of times.
我已经在我的项目中解决了这个问题,这是一个大型企业项目。我的团队懒得写空抓几百遍了。
Promise.prototype.then = function (onFulfilled, onRejected) {
return baseThen.call(this, (x: any) => {
if (onFulfilled)
onFulfilled(x);
}, (x: any) => {
if (onRejected)
onRejected(x);
});
};

