当 Promise 被 reject 且没有 reject 处理器的时候,会触发 unhandledrejection 事件;这可能发生在 window 下,但也可能发生在 Worker 中。这对于调试和为意外情况提供后备错误处理非常有用。
unhandledrejection 继承自 PromiseRejectionEvent,而 PromiseRejectionEvent 又继承自 Event。因此unhandledrejection 含有 PromiseRejectionEvent 和 Event 的属性和方法。主要包含两个有用的属性:
1、promise
特定的被 reject 且没有 reject 处理器的 Promise
2、reason
将会传入异常处理方法中的错误原因
可以使用 window.onunhandledrejection 来捕获未处理的 Promise 拒绝,并获取调用栈。
window.addEventListener('unhandledrejection', event => { console.error('Unhandled rejection:', event.reason.stack);});
new Promise((resolve, reject) => { // Some asynchronous operation reject(new Error('Something went wrong'));});
如果 reject()
的参数不是一个 Error
对象,而是其他类型的数据(例如字符串、数字、对象等),那么默认情况下是无法直接获取调用栈信息的。调用栈信息通常与 Error
对象相关联,因为 Error
对象在创建时会捕获当前的调用栈。
不过,你可以通过以下几种方法来确保在 reject()
时能够获取调用栈信息:
1、 总是使用 Error
对象: 最简单的方法是确保在调用 reject()
时总是传递一个 Error
对象。
new Promise((resolve, reject) => { reject(new Error('Something went wrong'));}).catch(error => { console.error('Error stack:', error.stack);});
2、 手动捕获调用栈: 如果你需要传递其他类型的数据,可以在捕获错误时创建一个 Error
对象以获取调用栈。
new Promise((resolve, reject) => { const error = new Error(); error.data = 'Some additional data'; reject(error);}).catch(error => { console.error('Error stack:', error.stack); console.log('Additional data:', error.data);});
3、 自定义包装错误: 创建一个自定义错误类或包装函数来确保调用栈信息被捕获。
function createErrorWithStack(message) { const error = new Error(message); Error.captureStackTrace(error, createErrorWithStack); return error;}
new Promise((resolve, reject) => { reject(createErrorWithStack('Some custom message'));}).catch(error => { console.error('Error stack:', error.stack);});
4、 在错误处理逻辑中创建 Error
对象: 如果你无法控制 reject()
的参数类型,可以在 .catch()
中创建一个 Error
对象来获取调用栈。
new Promise((resolve, reject) => { reject('Some error message');}).catch(reason => { const error = new Error('Caught error'); console.error('Error stack:', error.stack); console.log('Original reason:', reason);});
使用这些方法,可以确保在处理 Promise 错误时始终能够获取调用栈信息,从而更好地进行调试。