try...catch、express与co错误捕获
youngwind opened this issue · 0 comments
youngwind commented
原因
try catch捕获错误这个我原先知道,但是与express和co结合起来的时候我就觉得其中有些微妙的变化,决定好好研究一下。
#1. try..catch
JSON.parse('a');
console.log('finish');
这段代码会在执行第一行的时候报错,程序中断,不会执行第二行。
try{
JSON.parse('a');
} catch(e) {
console.log(e);
}
console.log('finish');
这段代码会在执行第二行的时候报错,但是错误会被catch捕获,输出错误信息,程序得以继续执行,输出'finish'
ok,下面我们再看看try...catch能不能捕获throw抛出的错误
try{
throw new Error('错误信息');
} catch(e) {
console.log(e);
}
console.log('finish');
结果证明是可以的。
然后,我们再看看能不能捕获异步的错误
try{
setTimeout(function(){
JSON.parse('a')
},1000)
} catch(e) {
console.log(e);
}
console.log('finish')
先输出'finish',1s之后再报错。注意,是报错,而不是输出错误,也就是说,try...catch没法捕获异步错误.
怎么办?
node有一个domain模块可以解决这个问题,参考这里,不过看起来老负责了,我好想还用不到,以后再研究。
express错误捕获
ok,接下来我们看看在express里面错误是如何被捕获和传递的。
// 假设我们在访问首页的时候抛出错误
router.get('/', function (req, res, next) {
throw new Error('访问首页出错');
});
// 然后app.js里面有两个错误处理中间件
app.use(function (err, req, res, next) {
console.log('经过第一个错误处理中间件');
next(err);
});
app.use(function (err, req, res, next) {
console.log('经过第二个错误处理中间件');
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
结果发现,首页抛出的错误会先被第一个错误处理中间件捕获处理,然后又传递给第二个错误中间件处理。关于更详细的express里面的错误捕获和传递机制可以参考这里
然后,我们看看如果在首页的地方异步执行的时候报错会怎么样呢?
router.get('/', function (req, res, next) {
setTimeout(function () {
throw new Error('异步错误');
}, 2000)
res.render('index', {title: 'Express'});
});
执行结果:访问首页正常,不报错。但是2s之后后端报错,程序中断执行。也就是说,这种异步错误,express错误处理中间件是没有办法捕获的。怎么办,我尝试调换一下顺序。
router.get('/', function (req, res, next) {
setTimeout(function () {
throw new Error('异步错误');
res.render('index', {title: 'Express'});
}, 2000)
});
执行结果:访问首页,延时2s,之后首页访问返回错误,后端报错,程序中断执行。那么,像这种异步抛出的错误,如何让express捕获到呢?下面我们看看co
co
//未完待续......