const IGNORABLE_SCRIPT_ERRORS = [ 'ResizeObserver loop completed with undelivered notifications.', 'ResizeObserver loop limit exceeded' ] function normalizeErrorMessage(message) { if (typeof message === 'string') { return message } if ('message' in message && typeof message.message === 'string') { return message.message } return '' } function isIgnorableScriptError(message, source) { const normalizedMessage = normalizeErrorMessage(message) if (!normalizedMessage) { return false } if (IGNORABLE_SCRIPT_ERRORS.some((item) => normalizedMessage.includes(item))) { return true } if (normalizedMessage === 'Script error.' && source === '') { return true } return false } function vueErrorHandler(err, instance, info) { console.error('[VueError]', err, info, instance) } function scriptErrorHandler(message, source, lineno, colno, error) { if (isIgnorableScriptError(message, source)) { return true } console.error('[ScriptError]', { message, source, lineno, colno, error }) return true } function registerPromiseErrorHandler() { window.addEventListener('unhandledrejection', (event) => { console.error('[PromiseError]', event.reason) }) } function registerResourceErrorHandler() { window.addEventListener( 'error', (event) => { const target = event.target if ( target && (target.tagName === 'IMG' || target.tagName === 'SCRIPT' || target.tagName === 'LINK') ) { console.error('[ResourceError]', { tagName: target.tagName, src: target.src || target.src || target.href }) } }, true // 捕获阶段才能监听到资源错误 ) } function setupErrorHandle(app) { app.config.errorHandler = vueErrorHandler window.onerror = scriptErrorHandler registerPromiseErrorHandler() registerResourceErrorHandler() } export { registerPromiseErrorHandler, registerResourceErrorHandler, scriptErrorHandler, setupErrorHandle, vueErrorHandler }