使用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 捕获到错误后,我都在控制台输出了一行提示信息 "捕获到错误" 当前进程并没有因为异常而挂掉,这就是我们要的效果.
使用domain模块捕获异步回调中的异常的更多相关文章
- node.js 使用domain模块捕获异步回调中的异常
和其他服务器端语言相比,貌似node.js 对于异常捕捉确实非常困难. 首先你会想到try/catch ,但是在使用过程中我们会发现并没有真正将错误控制在try/catch 语句中. 为什么? 答案是 ...
- Android异步回调中的UI同步性问题
Android程序编码过程中,回调无处不在.从最常见的Activity生命周期回调开始,到BroadcastReceiver.Service以及Sqlite等.Activity.BroadcastRe ...
- [置顶] Ajax程序:处理异步调用中的异常(使用Asp.Net Ajax内建的异常处理方法)
无论在Window应用程序,还是Web应用程序以对用户友好的方式显示运行时的异常都是很有必要,尤其对于可能有很多不确定因素导致异常的Web应用程序;在传统的Web开发中,处理异常的方式——设计专门一个 ...
- js即时函数在异步回调中的运用
在编程中我们会接触到循环和异步编程的情况,这时异步回调执行逻辑就会出现问题.我们用setTimeout来模拟异步的: for(var i=0;i<3;i++){ setTimeout(funct ...
- java主线程捕获子线程中的异常
本文主要参考:<think in java> 好,下面上货. 正常情况下,如果不做特殊的处理,在主线程中是不能够捕获到子线程中的异常的. 例如下面的情况. package com.xuey ...
- 在异步回调中调用MessageBox.Show
public static void Test() { ThreadStart aThreadStart = delegate() { ); MessageBox.Show("Good!&q ...
- 【转】asp.net 利用Global.asax 捕获整个解决方案中的异常错误
之前做项目的时候都是在每个页面中处理这不同的异常信息,一个页面数下来,很多个try{}catch{}语句块,令整个代码结构有些不够美观. 今天看到一篇帖子,是关于利用全局应用程序类来帮忙获取异常信息, ...
- MVC与WebApi中的异常过滤器
一.MVC的异常过滤器 1.自定义MVC异常过滤器 创建一个类,继承HandleErrorAttribute即可,如果不需要作为特性使用直接实现IExceptionFilter接口即可, 注意,该 ...
- 如何优雅的处理Nodejs中的异步回调
前言 Nodejs最大的亮点就在于事件驱动, 非阻塞I/O 模型,这使得Nodejs具有很强的并发处理能力,非常适合编写网络应用.在Nodejs中大部分的I/O操作几乎都是异步的,也就是我们处理I/O ...
随机推荐
- 针对特定XML的解析器XMLParser
一.建立网页库和偏移文件 为文本搜索引擎建立网页库,首先要把所有的网页(这里是文章)格式化,并保存到指定的格式中.如以下格式: | ...
- Android项目中的换肤总结
纵观现在各种Android app,其换肤需求可以归为 白天/黑夜主题切换(或者别的名字,通常2套),如同花顺/自选股/天天动听等,UI表现为一个switcher. 多种主题切换,通常为会员特权,如Q ...
- R语言︱ 数据库SQL-R连接与SQL语句执行(RODBC、sqldf包)
要学的东西太多,无笔记不能学~~ 欢迎关注公众号,一起分享学习笔记,记录每一颗"贝壳"~ --------------------------- 数据库是极其重要的R语言数据导入源 ...
- Flex中通过RadioButton进行切换
1.页面切换 <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx=& ...
- USB转串口驱动代码分析
1.USB插入时,创建设备 [plain] view plaincopy DriverObject->DriverExtension->AddDevice = USB2COM_PnPAdd ...
- Caused by: java.lang.ClassNotFoundException: com.mchange.v2.ser.Indirector
1.错误描述 usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] [ -nonaming ] { -help ...
- No bean named 'cxf' is defined
1.错误描述 严重:Exception starting filter CXFServlet org.springframework.beans.factory.NoSuchBeanD ...
- canvas动画:自由落体运动
经过前面的文章,我们已经能够在canvas画布上画出各种炫酷的图形和画面,但是这些画面都是禁止的,怎么样才能让他们动起来呢? 如何绘制基本图形可以参考:canvas基本图形绘制 如何对基本图形移动旋转 ...
- Dynamics 365 Online-60000 API Limits
最近,Dynamics 365官方文档有最新的发布,就是从2018.3.19开始,会对API请求的数目有个限制:在连续的5分钟里,一个连接用户,针对一个CRM Organization,API请求数不 ...
- Java百度地图经纬度纠偏
在国内使用电子地图获取到的经纬度都不是真实的经纬度,而是经过一定的算法在真实的经纬度上添加了一个偏移量,且不同的地图有不同的算法.现在告诉大家在java中怎样对百度地图进行纠偏,主要实现将真实的经纬度 ...