使用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 ...
随机推荐
- 网络基础Cisco路由交换三
热备份路由协议HSRP:Cisco私有协议 确保了当网络边缘设备或接入链路出现故障时,用户通信能迅速并透明地恢复,以此为ip网络提供余性,通过使用同意虚拟ip地址和虚拟mac地址,LAN网段上的两台或 ...
- 在Ubuntu16.04.4上安装jdk
在Ubuntu16.04.4上安装jdk 一.安装步骤 1.下载jdk安装包 首先我们在oracle官网上下载jdk-8u161-linux-x64.tar.gz,当然也可以下载其他版 ...
- 解决MyEclipse中的Building workspace问题
解决MyEclipse中的Building workspace问题 1.方法一 点击"Project",取消勾选"Build Automatically" 2. ...
- MyEclipse弹出提示窗口
MyEclipse弹出提示窗口 1.弹窗如下
- 小程序for循环中通过index实现单个点击事件
<!--xml--> <view class='content3-list' wx:for="{{listItems}}" > <view class ...
- Python 环境的搭建
Python最新源码,二进制文档,新闻资讯等可以在Python的官网查看到: Python官网:http://www.python.org/ 你可以在以下链接中下载 Python 的文档,你可以下载 ...
- ThinkCMF的跳转303 404等页面的方法
1. 控制器方法: return $this->redirect('http://www.thinkcmf.cmf',[],301); 或者助手函数: return redirect('http ...
- 【深入理解JVM】类加载器与双亲委派模型
原文链接:http://blog.csdn.net/u011080472/article/details/51332866,http://www.cnblogs.com/lanxuezaipiao/p ...
- [BZOJ1003] [ZJOI2006] 物流运输trans (最短路 & dp)
Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格 ...
- sqlserver存储过程及临时表在统计中的应用
use ResourceShare --统计使用情况 alter PROCEDURE StaSheryUse @start datetime, @end datetime, @orgId int AS ...