使用节点7异步/等待来纠正控制器

时间:2017-04-19 15:34:44

标签: node.js

让我们看看下面修改过的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);
});

1 个答案:

答案 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();
}));

您将获得正确的状态代码,不再有超时。

如果您不想自己包装,还可以使用几个模块: