window.addEventListener('error', function (e) { var stack = e.error.stack; var message = e.error.toString(); if (stack) { message += '\n' + stack; } var xhr = new XMLHttpRequest(); xhr.open('POST', '/log', true); // Fire an Ajax request with error details xhr.send(message); });
通过日志可以看到,具体什么情况触发了什么错误。在调试时调用堆栈也会非常有用。你 可以分析log,看到什么条件下触发了错误。
注意:
如果跨域脚本是不会看到错误的。 在JS中,错误信息仅仅是允许在同一个域中。
个人想法
更多的时候,代码抛出了异常,我们更关注的是在运行时,某个变量的值是什么,是否这个变量的值导致了错误,所以打印出调用时的跟多的信息更重要。
4.2 Node.js全局错误捕获
Node.js本身的异常处理要复杂得多,因为涉及到了进程或线程抛出异常的问题。
基于Koa的全局错误处理
nodejs是error-first的异步处理机制,此处底层会调用net模块的listen方法并在错误发生时执行回调。
app.listen(app.config.listenPort, (err) => { if (err) throw err app.logger.info(`> Ready on :${app.config.listenPort}`) })
路由错误处理
对于每个路由,它可能也会有不同的错误处理逻辑,这时路由进来的请求就需要根据情况返回不同的异常码和信息。
router.get('/loginAuth', async (ctx, next) => { try { const code = query.code const res = await requestToken(code) if (res.data.code !== 0) { ctx.app.logger.error(`request token error.Code is ${res.data.code} || response is: ${JSON.stringify(res.data.data)} || msg: ${res.data.message}`) ctx.body = { code: 10000, message: `request token by code error` } } else { ctx.body = res.data } } catch (err) { ctx.app.logger.error(`request api has exception ${ctx.request.url} || ${err.code} || ${err.message} || ${err.stack}`) ctx.body = { code: 500, message: `Error response` } } })
5. 总结
通常异常可能是预期的或者超出预期的,不管怎样,使用try/catch没有问题。
对于超出预期的错误,尽量使用catch来保证它们会被捕获到。
把错误处理器添加到window对象上,它会捕获到异步错误,符合了DRY和SOLID原则。一个全局的错误处理器可以帮你保持异步代码整洁。