Javascript Nodejs+Mongoose中的异步/等待

Javascript Nodejs+Mongoose中的异步/等待,javascript,node.js,express,mongoose,async-await,Javascript,Node.js,Express,Mongoose,Async Await,我对Promises和async/await编程还不熟悉,但我不确定自己是否理解得很清楚。我正在Nodejs中用Express、Mongoose和MongoDB创建一个API。 我看过很多关于如何处理异步性的教程,但都是关于路由和DB查询位于同一文件中的NodeJs项目。 例如: 然而,为了清楚起见,我已将路由与控制器分离,但我严重怀疑我是否正确执行了路由。这是我的密码: 路由器.js controller.js 我曾尝试console.log stuff来检查打印的内容,但我意识到,由于等待部

我对Promises和async/await编程还不熟悉,但我不确定自己是否理解得很清楚。我正在Nodejs中用Express、Mongoose和MongoDB创建一个API。 我看过很多关于如何处理异步性的教程,但都是关于路由和DB查询位于同一文件中的NodeJs项目。 例如:

然而,为了清楚起见,我已将路由与控制器分离,但我严重怀疑我是否正确执行了路由。这是我的密码:

路由器.js

controller.js

我曾尝试console.log stuff来检查打印的内容,但我意识到,由于等待部分的原因,这整段代码将等待查询完成。 这是否得到了很好的实施?我如何测试它

版本: nodejsv10.16.3
Mongoose v5.7.1

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

module.exports.view=async functionreq,res,next{ 试一试{ var something=wait something.findByIdreq.params.id.orFail; res.sendsome; }犯错误{ nexterr; } }; 然后在路由器中,它将是:

获取'/something/:id',somethingController.view; 这样做将允许您在Nexter将控制器操作发送到全局错误处理程序之前,操纵和处理该控制器操作的特殊错误情况

现在我不确定这是否是您所期望的,但您可能希望调用.orFail进行查询。这样,如果找不到具有指定ID的某物,就会抛出错误。否则,something变量将为null。但这完全取决于您希望API如何工作


此外,当您定义一个异步函数时,基本上是说该函数返回一个承诺。wait语句基本上告诉程序暂停函数,直到承诺得到解决。在本例中,wait将等待数据库返回结果,然后再继续控制器操作。Express将神奇地处理等待您的异步路由方法和中间件。

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

module.exports.view=async functionreq,res,next{ 试一试{ var something=wait something.findByIdreq.params.id.orFail; res.sendsome; }犯错误{ nexterr; } }; 然后在路由器中,它将是:

获取'/something/:id',somethingController.view; 这样做将允许您在Nexter将控制器操作发送到全局错误处理程序之前,操纵和处理该控制器操作的特殊错误情况

现在我不确定这是否是您所期望的,但您可能希望调用.orFail进行查询。这样,如果找不到具有指定ID的某物,就会抛出错误。否则,something变量将为null。但这完全取决于您希望API如何工作


此外,当您定义一个异步函数时,基本上是说该函数返回一个承诺。wait语句基本上告诉程序暂停函数,直到承诺得到解决。在本例中,wait将等待数据库返回结果,然后再继续控制器操作。Express将神奇地处理等待您的异步路由方法和中间件。

首先,您不需要异步中间件。让我给出一个完整的示例,说明如何在保持控制器异步的同时分离路由和控制器:

控制器

您应该将异步调用包装在try/catch块中

路线

然后,您只需在路线中呼叫控制器,如下所示:

router.get('/:id', Controller.findByID)
就这样。在路由上不需要任何额外的异步调用

如果您有想要添加路线的中间件,您可以这样做:

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

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

如果这有帮助,请告诉我。首先,您不需要异步中间件。让我给出一个完整的示例,说明如何在保持控制器异步的同时分离路由和控制器:

控制器

您应该将异步调用包装在try/catch块中

路线

然后,您只需在路线中呼叫控制器,如下所示:

router.get('/:id', Controller.findByID)
就这样。在路由上不需要任何额外的异步调用

如果您有想要添加路线的中间件,您可以这样做:

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

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

让我知道这是否有帮助

您可以而且可能应该将其简化为路由器。获取'/something/:id',asyncMiddlewaresomethingController.findById;如果我这样做,它是否作为异步函数处理?我想我在一开始就必须指定异步函数@BergiYou可以而且可能应该将其简化为router.get'/something/:id',asyncMiddlewaresomethingController.findById;如果我这样做,它是否作为异步函数处理?我想我总是必须指定异步
首先,非常感谢您的回答。也就是说,我已经读到中间件用于避免在每个函数中都有try/catch实例。这样你就可以把它放在路由中,当代码看起来更有条理、更简单的时候,把它忘掉。为什么不建议这样做?而且,我也看到一些文章没有使用mongoose db查询末尾的.exec。然而,他说,这是完全成熟的承诺所必需的。默认情况下Mongoose查询是异步的吗?或者实际上需要.exec?默认情况下,它们不是异步的,您必须将查询放入异步函数中,然后等待结果。正如文档所说,你可以使用.exec来获得一个完整的承诺,如果你愿意,你可以使用.then和.catch。我理解,但我的问题是:如果我不使用.exec或.then,会发生什么?它们是否仍然是异步的,因为函数是用async声明的,而我正在等待结果?这就是应用异步性所需要的全部吗。记住,当你使用wait时,你是在等待承诺的结果。2.当您使用async声明并等待承诺的响应时,它是异步的,并且为了使查询成为一个完整的承诺,您使用了。首先,非常感谢您的回答。也就是说,我已经读到中间件用于避免在每个函数中都有try/catch实例。这样你就可以把它放在路由中,当代码看起来更有条理、更简单的时候,把它忘掉。为什么不建议这样做?而且,我也看到一些文章没有使用mongoose db查询末尾的.exec。然而,他说,这是完全成熟的承诺所必需的。默认情况下Mongoose查询是异步的吗?或者实际上需要.exec?默认情况下,它们不是异步的,您必须将查询放入异步函数中,然后等待结果。正如文档所说,你可以使用.exec来获得一个完整的承诺,如果你愿意,你可以使用.then和.catch。我理解,但我的问题是:如果我不使用.exec或.then,会发生什么?它们是否仍然是异步的,因为函数是用async声明的,而我正在等待结果?这就是应用异步性所需要的全部吗。记住,当你使用wait时,你是在等待承诺的结果。2.当您使用async声明并等待承诺的响应时,它是异步的,为了使查询成为一个完全的承诺,您可以使用.exec
router.get('/:id', Controller.findByID)
//for single middleware
router.get('/:id',somethingMiddle,Controller.findByID)

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