让我们看看下面修改过的Restify示例,该示例现在包含Node 7 / 8s async / await support。
我对在express / restify / etc中正确实现这个问题略有顾虑。我关心的是事件循环中的承诺超过它所需的时间......我知道这不是一个承诺,但是我应该关注这个实现吗?我还没有发现任何问题。
'use strict';
const restify = require('restify');
const User = require('./models/User');
const server = restify.createServer({
name: 'myapp',
version: '1.0.0'
});
server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());
server.get('/echo/:name', async function (req, res, next) {
try {
const user = await User.findOne({
name: req.params.name;
});
res.send(user.get({plain: true}));
} catch (error) {
console.error(error);
res.send(500);
}
return next();
});
server.listen(8080, function () {
console.log('%s listening at %s', server.name, server.url);
});
答案 0 :(得分:1)
使用async
函数而不是接受回调的常规函数存在问题,因为错误的处理方式不同。
在回调函数(又名“err-backs”)中,无论执行是否成功,都必须调用回调。第一个参数是一个错误对象。
async
函数只是在出现任何错误(同步或异步)时返回被拒绝的承诺。
因此默认情况下,Express.js / Restify期望定期错误。如果你传递了async
函数并且它失败了,Express.js / Restify将继续等待调用回调而忽略被拒绝的承诺。它根本不知道返回的承诺而不是处理它。
最后,根本不会调用回调,端点将超时。
所以你将无法正确处理错误。
你可以尝试一下:
server.get('/echo/:name', async function (req, res, next) {
throw new Error();
});
因此,根据经验,我建议不要混合使用概念,也不要将回调传递给异步函数。这是一面红旗。
为了解决这个问题,你需要使用这样的包装器,例如:
const wrap = function(fn) {
return function(req, res, next) {
return fn(req, res, next).catch(function(err) {
return next(err);
});
};
};
server.get('/echo/:name', wrap(async function (req, res, next) {
throw new Error();
}));
您将获得正确的状态代码,不再有超时。
如果您不想自己包装,还可以使用几个模块: