繁体   English   中英

Nodejs + ZCCADCDEDB567ABAE643E15DCF0974E503Z 中的异步/等待

[英]Async/await in Nodejs + Mongoose

我是 Promises 和 async/await 编程的新手,我不确定我是否理解正确。 我正在 Nodejs 中创建一个 API,使用 Express、ZCCADCDEDB567ABAE643E15DCF0974E503Z 和 MongoDB。 我看过很多关于如何处理异步性的教程,但它们都是关于路由和数据库查询在同一个文件中的 NodeJs 项目。 例子:

const asyncMiddleware = fn =>
  (req, res, next) => {
    Promise.resolve(fn(req, res, next))
      .catch(next);
};

router.get('/users/:id', asyncMiddleware(async (req, res, next) => {
    const something = await getSomethingFromDb({ id: req.params.id })
    res.json(something);
}));

但是,为了清楚起见,我已将路由与 controller 分开,但我非常怀疑我是否正确地完成了它。 这是我的代码:

路由器.js

const asyncMiddleware = fn =>
  (req, res, next) => {
    Promise.resolve(fn(req, res, next))
      .catch(next);
};

router.get('/something/:id', asyncMiddleware(async (req, res, next) => {
    const answer = await somethingController.findById(req, res, next)
}));

controller.js

exports.findById = async (req, res, next) => {
    const something = await Something.findById(req.params.id).exec();
    res.send(something);
};

我尝试使用 console.log() 来检查打印的内容,但我已经意识到,由于等待部分,整段代码将等待查询完成。 这实施得好吗? 我该如何测试它?

版本:NodeJs v10.16.3 ZCCADCDEDB567ABAE643E15DCF0974E503Z v5.7.1

首先,您不需要“asyncMiddleware”。 让我举一个完整的例子来说明如何分离路由和控制器,同时保持 controller 异步:

Controller

exports.findById = async (req, res, next) => {
    try{
       const something = await Something.findById(req.params.id).exec();
       res.send(something);
    }catch(err){
       return res.status(500).send({
        message: err.message
      })
    }   
};

您应该将async调用包装在 try/catch 块中。

路线

然后,您只需在您的路线中调用您的 controller ,如下所示:

router.get('/:id', Controller.findByID)

就是这样。 您的路由不需要任何额外的async调用。

如果你有中间件你想添加你的路由,你可以这样做:

//for single middleware
router.get('/:id',somethingMiddle,Controller.findByID)

//for multiple middleware
router.get('/:id',[somethingMiddle, anotherMiddle],Controller.findByID)

让我知道这是否有帮助

就个人而言,我会坚持将 try-catch 用于我的异步功能,而不是使用中间件。 这可能类似于以下内容:

module.exports.view = async function(req, res, next) {
  try {
    var something = await Something.findById(req.params.id).orFail();
    res.send(something);
  } catch (err) {
    next(err);
  }
};

然后在您的路由器中,它只是:

router.get('/something/:id', somethingController.view);

这样做将允许您在next(err)将其发送到全局错误处理程序之前操纵和处理 controller 操作的特殊错误情况。

现在我不确定这是否是您所期望的,但您可能想在查询中调用.orFail() 这样,如果找不到具有指定 ID 的“某物”,则会引发错误。 否则, something变量将为 null。 但这完全取决于您希望 API 到 function 的方式。

此外,当您定义async function 时,基本上是说 function 返回Promise await语句基本上告诉程序暂停 function 直到 promise 得到解决。 在此示例中, await将等待数据库返回结果,然后再继续执行 controller 操作。 Express 将神奇地处理等待您的async路由方法和中间件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM