Express 5将自动处理async
错误
https://expressjs.com/en/guide/error-handling.html目前已经明确说明:
Starting with Express 5, route handlers and middleware that return a Promise will call next(value) automatically when they reject or throw an error. For example:
app.get('/user/:id', async function (req, res, next) {
var user = await getUserById(req.params.id)
res.send(user)
})
If getUserById throws an error or rejects, next will be called with either the thrown error or the rejected value. If no rejected value is provided, next will be called with a default Error object provided by the Express router.
我们可以按照以下方式进行测试:
const assert = require('assert')
const http = require('http')
const express = require('express')
const app = express()
app.get('/error', async (req, res) => {
throw 'my error'
})
const server = app.listen(3000, () => {
function test(path, method, status, body) {
const options = {
hostname: 'localhost',
port: server.address().port,
path: path,
method: method,
}
http.request(options, res => {
console.error(res.statusCode);
assert(res.statusCode === status);
}).end()
}
test('/error', 'GET', 500)
})
express@5.0.0-alpha.8
版本的终端输出是预期的:
500
Error: my error
at /home/ciro/test/express5/main.js:10:9
at Layer.handle [as handle_request] (/home/ciro/test/node_modules/router/lib/layer.js:102:15)
at next (/home/ciro/test/node_modules/router/lib/route.js:144:13)
at Route.dispatch (/home/ciro/test/node_modules/router/lib/route.js:109:3)
at handle (/home/ciro/test/node_modules/router/index.js:515:11)
at Layer.handle [as handle_request] (/home/ciro/test/node_modules/router/lib/layer.js:102:15)
at /home/ciro/test/node_modules/router/index.js:291:22
at Function.process_params (/home/ciro/test/node_modules/router/index.js:349:12)
at next (/home/ciro/test/node_modules/router/index.js:285:10)
at Function.handle (/home/ciro/test/node_modules/router/index.js:184:3)
如果您在浏览器上访问它,您将看到一个HTML页面,上面写着“我的错误”。
如果您在express@4.17.1上运行完全相同的代码,则仅在终端上看到:
UnhandledPromiseRejectionWarning: my error
但不是
500
或者
my error
。这是因为请求永远停留在那里。如果你尝试在浏览器中打开它,你会更清楚地看到它的停滞。
待办事项:如何使其显示堆栈跟踪,而不仅仅是 my error
? Getting the stack trace in a custom error handler in Express?
Express 4 解决方案
对于 Express 4 的最简单解决方案就是在每个路由中加入一个 try
/catch
,如下所示:
app.get('/error', async (req, res, next) => {
try {
throw new Error('my error'
res.send('never returned')
} catch(error) {
next(error);
}
})
这将产生与Express 5相同的正确行为。
您还可以通过一些在express.js异步路由和错误处理中讨论的方法进一步优化此过程。
已在Node.js v14.16.0上进行了测试。