nodejs是异步IO执行,所以我们将try/catch放置异步回调函数中,当出现一个异常时,try/catch操作只能捕获当次事件循环内的异常,我们通过try 拿到这个错误时错过了当前程序运行堆栈。(或者理解成,异步错误发生时在try catch块结束时候,所以当然不会被catch)
之后 Node 会触发 uncaughtException事件,而在node.js原生的uncaughtException 处理事件是挂在 process 对象上,所以,如果一个异常出现时,当前运行的 process 会直接挂掉,导致错误永远不会走到 catch语句.
比如,在实际项目中,
var deserialize = require('deserialize'); // 假设 deserialize 是一个带有 bug 的第三方模块 // app 是一个 express 服务对象 app.get('/users', function (req, res) { mysql.query('SELECT * FROM user WHERE id=1', function (err, user) { var config = deserialize(user.config); // 假如这里触发了 deserialize 的 bug res.send(config); }); });
如果不幸触发了 deserialize 模块的 bug,这里就会抛出一个异常,最终结果是整个服务 crash。
当这种情况发生在 Web 服务上时结果是灾难性的。uncaughtException 错误会导致当前的所有的用户连接都被中断,甚至不能返回一个正常的 HTTP 错误码,用户只能等到浏览器超时才能看到一个no data received错误。
异常处理是程序运行中必须要关注的地方,当异常出现后,应该第一时间关注到,并且快速解决。大部分程序员们都不敢保证自己的代码百分比正确,所以应该在写代码时就要对异常提前做预防处理,尽量保证在异常出现时,给用户一个友好的提示,不至于服务挂起导致请求超时,并且能将异常信息做记录上报,方便后期排查解决。
一. 同步代码的异常捕获处理
// 同步代码中的异常使用try{}catch结构即可捕获处理。 try { throw new Error('错误信息'); } catch (e) { console.error(e.message); } // 可以正常捕获异常