如何定位未处理Promise拒绝的来源?及排查遇阻的异常问题
定位Sentry中陡增的
Event CustomEvent (type=unhandledrejection)错误来源 近期Sentry中标题为Event CustomEvent (type=unhandledrejection) captured as promise rejection的错误数量陡增,初步排查发现代码存在Promise被拒绝的情况,但无法定位具体位置。
已添加如下代码跟踪拒绝事件,但reason值始终为undefined。已知监听参数包含promise属性,但不知道如何从中提取有效信息,想确认是否能确定Promise的来源,以及具体操作方法:
window.addEventListener('unhandledrejection', ({ reason }) => { ErrorManagement.addTrace({ data: { reason }, level: 'info', message: 'unhandledrejection caught', category: 'error', }); });
更新1
尝试直接用window.addEventListener('unhandledrejection', console.error),能正常执行,但没比自定义处理程序多提供信息。
受启发尝试通过猴子补丁修改CustomEvent构造函数,控制台测试window.dispatch(new CustomEvent('unhandledrejection'))时能显示堆栈,但生产环境无效,推测是CustomEvent创建方式不同,但不确定原因:
class CustomEventWithStack extends CustomEvent<any> { stack?; constructor(type: string, eventInitDict?: CustomEventInit) { super(type, eventInitDict); if (type === 'unhandledrejection') { this.stack = (new Error()).stack; } } } CustomEventWithStack.prototype = CustomEvent.prototype; CustomEventWithStack.prototype.constructor = CustomEventWithStack; CustomEvent = CustomEventWithStack;
更新2
进一步尝试猴子补丁修改Promise:
window.addEventListener('unhandledrejection', (event) => { ErrorManagement.addTrace({ data: { reason: event.reason, stack: (event.promise as PromiseWithStack<any>).stack, }, level: 'info', message: 'unhandledrejection caught', category: 'error', }); }); class PromiseWithStack<T> extends Promise<T> { stack = new Error().stack; constructor(executor: (resolve: any, reject: any) => void) { super((resolve, reject) => { executor(resolve, (reason: any) => { if (reason === undefined) { reject({ stack: new Error().stack }); } }); }); } } window.Promise = PromiseWithStack; const originalFetch = fetch; window.fetch = (...args) => new PromiseWithStack((resolve, reject) => { originalFetch(...args).then(resolve, reject); });
但触发了新错误:Cannot read properties of undefined (reading 'stack')。于是检查事件监听中传入的事件内容:
data: { reason: event.reason, eventClass: event.constructor.name, promiseType: typeof event.promise, promiseClass: event.promise?.constructor.name, },
得到结果:
{ "eventClass": "CustomEvent", "promiseType": "undefined" }
现在产生新疑问:为什么CustomEvent会出现在'unhandledrejection'事件监听中?不确定是否需要单独提交新问题。
内容的提问来源于stack exchange,提问作者Lex
相关产品推荐
相关产品推荐

