【发布时间】:2020-08-03 22:01:50
【问题描述】:
当我仅使用 onunhandledrejection 处理程序捕获 Promise 拒绝时,如何确定它发生在哪里?
console.error = ()=>{}
window.addEventListener('unhandledrejection', (promiseRejectionEvent) => {
console.log('unhandled: ', Error().stack)
})
function main() {
new Promise(() => { throw null })
}
main()
如果您在运行此程序后检查浏览器的控制台,您将看到如下内容:
Error().stack 仅在其堆栈跟踪中包含拒绝处理函数本身(灰色输出 js:14:30)。但浏览器确实 似乎知道拒绝发生在哪里:还有另一个红色错误输出 (Uncaught (in promise) null),指向目标行 (js:18)。如何获取此线路信息?
似乎后者的输出是由浏览器的内部完成的,因为它不能通过覆盖console.error 来防止,就像上面的例子一样。只能通过调用promiseRejectionEvent.preventDefault() 来预防,如MDN 中所述。但我不想阻止它,而是取而代之,例如用于记录目的。
真实世界用例:当然可以不依赖onunhandledrejection 事件处理程序,例如通过添加.catch() 短语或至少抛出throw new Error(null)。但就我而言,我无法控制它,因为它是第三方代码。今天它在客户端的浏览器上意外抛出(可能是库错误),并且自动错误报告不包括堆栈跟踪。我试图缩小上述潜在问题的范围。谢谢!
编辑以响应 cmets:
将第三方代码包装在 try/catch 中? – 世界观
好点,但这无济于事,因为拒绝实际上发生在回调中:
window.addEventListener('unhandledrejection', (promiseRejectionEvent) => {
console.log('unhandled: ', Error().stack) // <- stack once again does *not* include "main()", it is only printed out in the console
})
function main() {
try {
thirdPartyModule()
} catch(e) {
// Never caught
console.log("caught:", e)
}
}
// Example code
// We cannot change this function
function thirdPartyModule() {
setTimeout(() =>
new Promise(() =>
{ throw null }))
}
main()
【问题讨论】:
-
将第三方代码包装在 try/catch 中?
-
@weltschmerz 是的,但是第三方代码实际上并没有返回一个 Promise,所以它不能被捕获。我用一个例子更新了答案。谢谢
标签: javascript promise stack-trace