3 回答
TA贡献1874条经验 获得超12个赞
并且永远不要在这个返回的 Promise 上调用 then()。使用这种模式是因为我们不依赖中间件函数的任何返回值吗?
是否可以只返回 Promises 而从不调用 then() 来获取它们的值,因为 Express 中的中间件没有返回有意义的值?
是的,如果您要跟踪的只是它是否被拒绝,因为它处理自己的成功完成,但您需要单独处理错误,那么您可以使用.catch()这实际上是您正在做的事情。这可以。
如果我经常这样做,我会切换到像 Koa 这样的承诺友好型框架,或者我会添加自己的承诺感知中间件注册。例如,下面是 Express 的一个附加组件,它为您提供了 Promise-aware 中间件:
// promise aware middleware registration
// supports optional path and 1 or more middleware functions
app.useP = function(...args) {
function wrap(fn) {
return async function(req, res, next) {
// catch both synchronous exceptions and asynchronous rejections
try {
await fn(req, res, next);
} catch(e) {
next(e);
}
}
}
// reconstruct arguments with wrapped functions
let newArgs = args.map(arg => {
if (typeof arg === "function") {
return wrap(arg);
} else {
return arg;
}
});
// register actual middleware with wrapped functions
app.use(...newArgs);
}
然后,要使用这个可感知承诺的中间件注册,您只需像这样注册它:
app.useP(async (req, res, next) => {
req.user = await User.findUser(req.body.id);
next();
});
而且,任何被拒绝的承诺都会自动为您处理。
这是一个更高级的实现。把它放在一个名为的文件中express-p.js:
const express = require('express');
// promise-aware handler substitute
function handleP(verb) {
return function (...args) {
function wrap(fn) {
return async function(req, res, next) {
// catch both synchronous exceptions and asynchronous rejections
try {
await fn(req, res, next);
} catch(e) {
next(e);
}
}
}
// reconstruct arguments with wrapped functions
let newArgs = args.map(arg => {
if (typeof arg === "function") {
return wrap(arg);
} else {
return arg;
}
});
// register actual middleware with wrapped functions
this[verb](...newArgs);
}
}
// modify prototypes for app and router
// to add useP, allP, getP, postP, optionsP, deleteP variants
["use", "all", "get", "post", "options", "delete"].forEach(verb => {
let handler = handleP(verb);
express.Router[verb + "P"] = handler;
express.application[verb + "P"] = handler;
});
module.exports = express;
然后,在你的项目中,而不是这个:
const express = require('express');
app.get(somePath, someFunc);
用这个:
const express = require('./express-p.js');
app.getP(somePath, someFunc);
然后,您可以自由使用这些方法中的任何一种,它们会自动处理从路由返回的被拒绝的 Promise:
.useP()
.allP()
.getP()
.postP()
.deleteP()
.optionsP()
在您创建的应用程序对象或您创建的任何路由器对象上。此代码修改原型,因此您在加载此模块后创建的任何应用程序对象或路由器对象将自动具有所有这些承诺感知方法。
TA贡献1848条经验 获得超6个赞
你在做什么是绝对好的。但对于那些想得太多的人来说,有一个简单的解决方案。只需重新编写asyncHandler.
const asyncHandler = fn => (req, res, next) => {
fn(req, res, next)
.catch(next);
}
我们不需要Promise.resolve()在asyncHandler. 因为fn是一个async函数,所以它返回一个承诺。catch()如果函数内部有错误,我们就可以承诺。
在这里我们没有从asyncHandler函数返回任何东西,因为我们不需要。
添加回答
举报