Error Handling(https://www.expressjs.com.cn/guide/error-handling.html)
本文的【错误处理】指Express如何捕获和处理(同步和异步的)错误。Express有一个默认的错误处理handler,所以一开始不是必须写自己的错误处理handler。
捕获错误
Catching Errors
保证Express会捕获运行路由handlers和中间件时发生的所有错误非常重要。
在路由handlers和中间件的同步代码中发生的错误不需要做额外的工作(Errors that occur in synchronous code inside route handlers and middleware require no extra work),Express会捕获和处理。
但路由handlers和中间件中调用的异步函数抛出的错误,我们就需要将异常捕获,使用next()函数 将错误传入(next(error)), 使Express能够捕获和处理这个错误。
tips:next函数除了传入字符串'route',其他参数都会被认为是错误,会跳过余下所有非错误处理的路由和中间件函数
//
app.get('/', [
function(req, res, next) {
fs.writeFile('/file-does-not-exit', data, function(err, data){
if(err) {
next(err);
} else {
res.send(data);
}
});
}
])
// 直接将next作为callback函数,
//有错误时next有参数 携带错误参数被Express error handler捕获并处理,
// 无错误时 next无参数 , 执行下一个handler
app.get('/', [
function(req, res, next) {
fs.writeFile('/file-does-not-exit', data, function(err, data){
if(err) {
next(err);
} else {
res.send(data);
}
});
}
])
// 需捕获异常
app.get('/', function (req, res, next) {
setTimeout(function () {
try {
throw new Error('BROKEN')
} catch (err) {
next(err)
}
}, 100)
})
// 使用promise 代替 try catch
app.get('/', function (req, res, next) {
Promise.resolve().then(function(){
throw new Error('BROKEN')
}).catch(next)
})
默认的错误处理函数
The default error handler
没有自定义错误处理函数,用next(error)传入错误的时候,express默认的错误处理函数进行处理,会同时输出调用栈信息(NODE_ENV的值为production时不会打印调用栈信息)
需要注意的一点是,如果已经开始写response,调用了next(error), Express的默认错误处理函数会关闭连接,此次请求会失败。
所以在自定义的error handler中,当header已经被发送给client端,发生错误的话需要将错误传给默认的错误处理函数(???)
如果你在你的代码调用next()出现错误多次,则会触发默认错误处理程序,即使自定义错误处理中间件已就绪也是如此(???)
function errorHandler (err, req, res, next) {
if (res.headersSent) {
return next(err)
}
res.status(500)
res.render('error', { error: err })
}
如何实现错误处理函数
Writing error handlers
定义错误处理中间件函数的方式与定义其他中间件函数一样,只是错误处理中间件的参数是4个 err, req,res ,next
我们需要在最后定义错误处理中间件函数,在其他的app.use 和路由调用之后。
中间件函数的返回值可以是任意格式,如html错误页面,简单的字符串信息 或json字符串
如果在error handler中没有调用next函数,则需要负责返回响应,否则请求会被挂起,并且不会被垃圾回收机制回收