Node 的异步特性是它最大的魅力,但是在带来便利的同时也带来了不少麻烦和坑,错误捕获就是一个。由于 Node 的异步特性,导致我们无法使用 try/catch 来捕获回调函数中的异常,例如:
try { console.log('进入 try/catch'); require('fs').stat('SOME_FILE_DOES_NOT_EXIST', function readCallback(err, content) { if (err) { throw err; // 抛出异常 } }); } catch (e) { // 这里捕获不到 readCallback 函数中抛出的异常 } finally { console.log('离开 try/catch'); }
运行结果是:
进入 try/catch 离开 try/catch test.js:7 throw err; // 抛出异常 ^ Error: ENOENT, stat 'SOME_FILE_DOES_NOT_EXIST'
上面代码中由于 fs.stat 去查询一个不存在的文件的状态,导致 readCallback 抛出了一个异常。由于 fs.read 的 异步特性,readCallback 函数的调用发生在 try/catch 块结束之后,所以该异常不会被 try/catch 捕获。之后 Node 会触发 uncaughtException 事件,如果这个事件依然没有得到响应,整个进程(process)就会 crash。
程序员永远无法保证代码中不出现 uncaughtException,即便是自己代码写的足够小心,也不能保证用的第三方模块 没有 bug,例如:
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 错误。
这是一种非常野蛮粗暴的异常处理机制,任何线上服务都不应该因为 uncaughtException 导致服务器崩溃。一个友 好的错误处理机制应该满足三个条件:
对于引发异常的用户,返回 500 页面
其他用户不受影响,可以正常访问
不影响整个进程的正常运行
很遗憾的是,保证 uncaughtException 不影响整个进程的健康运转是不可能的。当 Node 抛出 uncaughtException 异常时就会丢失当前环境的堆栈,导致 Node 不能正常进行内存回收。也就是说,每一次 uncaughtException 都有可能 导致内存泄露。
既然如此,退而求其次,我们可以在满足前两个条件的情况下退出进程以便重启服务。
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索异常
, node
, deserialize
, try
, catch
, 一个
, ENOENT
, fs.stat方法
捕获超时事件
uncaught exception、nodeletexception、nodejs exception、退出node命令行、node 退出,以便于您获取更多的相关知识。