Mar*_*nde 5 javascript node.js express es6-promise
我有一个asyncExpress中间件,因为我想在其中使用中间件await来清理我的代码。
const express = require('express');
const app = express();
app.use(async(req, res, next) => {
await authenticate(req);
next();
});
app.get('/route', async(req, res) => {
const result = await request('http://example.com');
res.end(result);
});
app.use((err, req, res, next) => {
console.error(err);
res
.status(500)
.end('error');
})
app.listen(8080);
Run Code Online (Sandbox Code Playgroud)
问题是当它拒绝时,它不会进入我的错误中间件,但是如果我删除了async关键字,并且throw在中间件内部,它就会去。
app.get('/route', (req, res, next) => {
throw new Error('Error');
res.end(result);
});
Run Code Online (Sandbox Code Playgroud)
所以我得到的UnhandledPromiseRejectionWarning不是输入我的错误处理中间件,而是如何让错误冒泡并表达处理它?
Adr*_*ian 25
好吧,我找到了这个 - https://github.com/davidbanham/express-async-errors/,然后需要脚本,你很高兴
const express = require('express');
require('express-async-errors');
Run Code Online (Sandbox Code Playgroud)
Mar*_*nde 12
问题是当它拒绝时,它不会进入我的错误中间件,但是如果我删除了async关键字并扔进了中间件中,它就会去。
express 目前不支持诺言,将来的版本可能会支持 express@5.x.x
因此,当您传递中间件函数时,express将在一个try/catch块内调用它。
Layer.prototype.handle_request = function handle(req, res, next) {
var fn = this.handle;
if (fn.length > 3) {
// not a standard request handler
return next();
}
try {
fn(req, res, next);
} catch (err) {
next(err);
}
};
Run Code Online (Sandbox Code Playgroud)
问题在于,该函数try/catch不会捕获函数Promise外部的拒绝,async并且由于express没有在中间件返回的.catch函数中添加处理程序Promise,因此您会得到UnhandledPromiseRejectionWarning。
最简单的方法是try/catch在中间件中添加,然后调用next(err)。
app.get('/route', async(req, res, next) => {
try {
const result = await request('http://example.com');
res.end(result);
} catch(err) {
next(err);
}
});
Run Code Online (Sandbox Code Playgroud)
但是,如果您有很多async中间件,则可能有些重复。
由于我喜欢中间件尽可能干净,并且通常让错误冒出来,因此我在async中间件周围使用了包装器,next(err)如果承诺被拒绝,它将调用,到达明确的错误处理程序并避免UnhandledPromiseRejectionWarning
const asyncHandler = fn => (req, res, next) => {
return Promise
.resolve(fn(req, res, next))
.catch(next);
};
module.exports = asyncHandler;
Run Code Online (Sandbox Code Playgroud)
现在您可以这样称呼它:
app.use(asyncHandler(async(req, res, next) => {
await authenticate(req);
next();
}));
app.get('/async', asyncHandler(async(req, res) => {
const result = await request('http://example.com');
res.end(result);
}));
// Any rejection will go to the error handler
Run Code Online (Sandbox Code Playgroud)
还有一些可以使用的软件包
用 asyncHandler 回答是好的和有用的,但是在每个路由中编写这个包装器仍然不舒服。我建议改进它:
const asyncHandler = fn => (req, res, next) => {
return Promise
.resolve(fn(req, res, next))
.catch(next)
}
const methods = [
'get',
'post',
'delete' // & etc.
]
function toAsyncRouter(router) {
for (let key in router) {
if (methods.includes(key)) {
let method = router[key]
router[key] = (path, ...callbacks) => method.call(router, path, ...callbacks.map(cb => asyncHandler(cb)))
}
}
return router
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以这样做:
const router = toAsyncRouter(express().Router())
router.get('/', someAsyncController)
Run Code Online (Sandbox Code Playgroud)
等等。
分钟前添加了一个 npm 模块async-express-decorator。
Express 5 现在处理异步承诺:
https://expressjs.com/en/guide/error-handling.html
从 Express 5 开始,返回 Promise 的路由处理程序和中间件将在拒绝或抛出错误时自动调用 next(value)。例如
您需要使用 try-catch 并在 catch 部分中将错误传递到 next() 参数中,如下所示 -
async create(req, res, next) {
try {
const userProp = req.body;
const user = new User(userProp)
const response = await user.save()
const token = await user.createJWSToken()
res.send({response, token})
} catch (err){
next(err)
}
}
Run Code Online (Sandbox Code Playgroud)
显然,将此快速中间件放在您的 index.js 文件中。
app.use((err, req, res, next) => {
res.status(422).send({ error: err.message });
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4598 次 |
| 最近记录: |