如何简化在使用相同参数的路由中创建回调函数的过程?



我被困在节点/快递中创建重用相同参数的包装器回调函数的最佳方法上。

问题是验证需要与回调相同的参数。有没有办法简化这一点?我已经在堆栈和谷歌上寻找过这个,但找不到答案。我不想在实际调用中写 req、res、next 两次。我知道第一个 req,res,下一个被漏斗到回调中,但这样写仍然感觉很奇怪。感觉肯定有更好的方法,但我不知道那是什么。

情况如下:

function verifyCaptcha(req, res, next, callback) {
let captchaResponse = req.body.captchaResponse;
let captchaSecret = "it's a secret";
let captchaURL = "https://www.google.com/recaptcha/api/siteverify?"
+ "secret=" + encodeURIComponent(captchaSecret) + "&"
+ "response=" + encodeURIComponent(captchaResponse) + "&"
+ "remoteip" + encodeURIComponent(req.connection.remoteAddress);
// request is ASYNC, that's why I need the callback
request(captchaURL, function(error, response, body) {
callback(req, res, next);
return;
});
};

router.post('/login', function(req, res, next) {
// example call INSIDE a route (here's the problem b/c params are repeated in the call
verifyCaptcha(req, res, next, function(req, res, next){
// do stuff
});
};

承诺应该避免回调地狱。所有流行的基于回调的库都有承诺的对应物,这对request来说是request-promise。这可以与async..await同步的方式编写:

const request = require('request-promise');
async function verifyCaptcha(req, res) {
let captchaResponse = req.body.captchaResponse;
let captchaSecret = "it's a secret";
let captchaURL = "https://www.google.com/recaptcha/api/siteverify?"
+ "secret=" + encodeURIComponent(captchaSecret) + "&"
+ "response=" + encodeURIComponent(captchaResponse) + "&"
+ "remoteip" + encodeURIComponent(req.connection.remoteAddress);
const result = await request(captchaURL);
...
};

router.post('/login', async function(req, res, next) {
try {
await verifyCaptcha(req, res);
} catch (err) {
next(err);
}
};

正如这个问题所解释的,Express 本身不支持 promise,所有拒绝都应该由开发人员处理,async中间件/处理程序函数体应该用try..catch包装。

根据快递文档,您可以通过简单地将中间件添加到路由调用来链接中间件。

http://expressjs.com/en/4x/api.html#app.use

这允许您执行此操作:

function verifyCaptcha(req, res, next) {
let captchaUrl = ...
request(captchaUrl, function(error, response, body) {
if (error) res.sendStatus(403)
next()
}
}
router.post('/login', verifyCaptcha, function(req, res, next) {
// this will only run if verifyCaptcha calls next()
}

最终结果在实践中更具可读性。

最新更新