node.js 使用domain模块捕获异步回调中的异常
和其他服务器端语言相比,貌似node.js 对于异常捕捉确实非常困难.
首先你会想到try/catch ,但是在使用过程中我们会发现并没有真正将错误控制在try/catch 语句中.
为什么?
答案是这样的:
node.js 是异步IO执行,所以我们将try/catch 反正异步回调函数中,当出现一个异常的时候,我们try 拿到这个错误时应该错过了当前程序运行堆栈,
而在node.js原生的uncaughtException 处理事件却挂在 process 对象上,OMG,你可想而知,如果一个异常出现时,当前运行的 process 会直接挂掉,
导致错误永远不会走到 catch 语句.所以 try/catch 在异步回调中显得苍白无力,我们有什么办法控制这种异步回调的异常吗?
当然,我们下面来介绍一种比较有效的处理方法:
domain模块,这是node自带的一个模块,看名字确实很难联想到他是用来捕捉异常的,它能帮我们做一些try /catch无法做到的事情.
首先引用模块
var domain = require('domain');
如果你也使用Express框架,可以直接将domain 做成一个 Express 的中间件,这样所有的 request及response 中的异步错误都可以捕捉到.
app.configure(function () {
app.use(function (req, res, next) {
var reqDomain = domain.create();
reqDomain.on('error', function (err) { // 下面抛出的异常在这里被捕获,触发此事件
console.log('捕获到错误');
res.send(500, err.stack); // 成功给用户返回了 500
});
reqDomain.run(next);
});
});
上面这种写法是Express 的一个中间件写法, app.use(function(req,res,next){ .....}) 这是一个中间件,用来接收所有http请求,这里你可以捕获request 和 response 对象用来做一些过滤,逻辑判断等等,最后通过 next 来放行本次请求,那么这个中间件就完成了他的一次使命.
而我们为了让 domain 模块来接管所有的http请求中的异常,所以把它写成一个中间件是非常方便的.
然后我们在 process 上将未处理的异常捕捉一下,做到万无一失.
process.on('uncaughtException', function (err) {
console.error("uncaughtException ERROR");
if (typeof err === 'object') {
if (err.message) {
console.error('ERROR: ' + err.message)
}
if (err.stack) {
console.error(err.stack);
}
} else {
console.error('argument is not an object');
}
});
//下面我们来定义几个路由,测试一下.
app.get('/', function (req, res) {
levelDB.getData('test', function (err, v) {
//这里我从levelDB 中读取一条数据,需要引入 levelDB 模块.
err ? res.send({status: "fail"}) : res.send({status: "success", value: v});
});
})
//我们再想办法让程序出现一个异步异常
app.get('/err', function (req, res) {
//throw new Error('exception');
setTimeout(function () {
throw new Error('exception'); // 抛出一个异步异常
}, 1000);
})
//我们之所以想到用 setTimeout 就是想模拟一个异步的回调,如果你直接 throw new Error('exception');这样就不是异步了,直接会被 process 上的 uncaughtException 来接管.
通过上面定义的两个路由,我们来分别访问一下

这个路由我们从数据库读取了一条记录最后返回给客户端,中间没有出现任何异常.

这是我们模拟的一个异常已经被捕捉到,这是服务器端返回给客户端的一个500提示信息,这时我们再看一眼控制台,node 进程并没有挂掉.

每次 domian 捕获到错误后,我都在控制台输出了一行提示信息 "捕获到错误" 当前进程并没有因为异常而挂掉,这就是我们要的效果.
node.js 使用domain模块捕获异步回调中的异常的更多相关文章
- 使用domain模块捕获异步回调中的异常
和其他服务器端语言相比,貌似node.js 对于异常捕捉确实非常困难. 首先你会想到try/catch ,但是在使用过程中我们会发现并没有真正将错误控制在try/catch 语句中. 为什么? 答案是 ...
- 浅析 Node.js 的 vm 模块以及运行不信任代码
在一些系统中,我们希望给用户提供插入自定义逻辑的能力,除了 RPC 和 REST 之外,运行客户提供的代码也是比较常用的方法,好处是可以极大地减少在网络上的耗时.JavaScript 是一种非常流行而 ...
- Node.js:工具模块
ylbtech-Node.js:工具模块 1.返回顶部 1. Node.js 工具模块 在 Node.js 模块库中有很多好用的模块.接下来我们为大家介绍几种常用模块的使用: 序号 模块名 & ...
- Node.js的Formidable模块的使用
今天总结了下Node.js的Formidable模块的使用,下面做一些简要的说明. 1) 创建Formidable.IncomingForm对象 var form = new formidab ...
- Node.js的net模块
net模块提供了一个异步网络包装器,用于TCP网络编程,它包含了创建服务器和客户端的方法 创建TCP服务器 net.createServer方法 创建客户端去连接服务器 net.connect方法 简 ...
- 利用Node.js的Net模块实现一个命令行多人聊天室
1.net模块基本API 要使用Node.js的net模块实现一个命令行聊天室,就必须先了解NET模块的API使用.NET模块API分为两大类:Server和Socket类.工厂方法. Server类 ...
- Node.js入门:模块机制
CommonJS规范 早在Netscape诞生不久后,JavaScript就一直在探索本地编程的路,Rhino是其代表产物.无奈那时服务端JavaScript走的路均是参考众多服务器端语言来 ...
- 第5月第10天 node.js的request模块
1.node.js的request模块 http://www.cnblogs.com/meteoric_cry/archive/2012/08/18/2645530.html
- node.js使用mysql模块的坑
之前用node.js写的订餐系统,很容易挂掉,一直也没想去解决它.今天看了一下,试了试,原因是在连接数据库的时候没有对error事件进行处理,导致程序一直挂在那里,需要重启服务才能正常使用. ...
随机推荐
- Linux 离奇磁盘爆满解决办法
问题原因&通用解决步骤 频繁收到es数据节点磁盘使用监控告警,到es上查看,磁盘使用率40%,因此登录该告警服务器,df -h 查看,如图 发下根目录使用超过了80%,因此持续告警,按照以往办 ...
- IntelliJ IDEA 2019.3 代码提示忽略大小写(IDEA 2019版本如何设置代码提示不分大小写?)
最近在使用IDEA,发现每次只能进行完全匹配,且区分大小写,界面变了IDEA 2019.3 忽略大小写设置跟之前的版本稍微有点不同,跟之前的软件有点点区别,在此记录一下不区分大小写的方法. 1. 使用 ...
- 美和易思 MOOT去鼠标检测,快进,倍速,自动下一章
F12 放到 console 直接运行即可 或者油猴添加新脚本 核心去除网页绑定焦点事件代码: if (!-[1,] && !window.XMLHttpRequest || navi ...
- Java初学者作业——简单程序根据用户输入的会员类型以及购物金额,判断是否能够享受活动优惠
返回本章节 返回作业目录 需求说明: 超市周年庆举行购物满减活动,编写Java程序,根据用户输入的会员类型以及购物金额,判断是否能够享受活动优惠,会员类型的输入不限制大小写.具体获取规则:若为VIP会 ...
- CSS基础 精灵图的使用
使用步骤1.创建盒子 <div class="one"></div> 2.使用PxCook量取图标大小,将图标的宽高设置成为盒子的宽高 ...
- 初识python 之 mysql数据库基本操作
import pymysql 注:所有插入.修改.删除操作都必须要提交(conn.commit()) 连接数据库: conn = pymysql.connect( host = '127.0.0.1' ...
- Python常用功能函数总结系列
Python常用功能函数系列总结(一) 常用函数一:获取指定文件夹内所有文件 常用函数二:文件合并 常用函数三:将文件按时间划分 常用函数四:数据去重 Python常用功能函数系列总结(二) 常用函数 ...
- SYCOJ27猴子选大王
题目-猴子选大王 (shiyancang.cn) 一.出队顺序Description有M个人,其编号分别为1-M.这M个人按顺序排成一个圈.现在给定一个数N,从第一个人开始依次报数,数到N的人出列,然 ...
- CSS-选择器的使用
* 默认选择器,这个符号能匹配所有样式,所以如果没有额外定义就默认为这个样式,一般用于消除页面与浏览器的内外边距 <style> *{ padding:0; // 所有标签默认消除内边距 ...
- vue传参子传父
vue子传父用$emit实现 1.文件目录结构 2.parent父组件内容 <template> <div class="wrap"> <div> ...