node.js - 将回调传递给以await 为前缀的函数。执行顺序

标签 node.js asynchronous mongoose callback async-await

假设我们有一个包含汽车的 mongoDB,用户可以添加汽车。目的是防止多于一辆具有相同车牌的汽车被保存。堆栈是node/express 和mongoose。

场景:数据库中已存在具有所提供车牌的汽车。

第一次尝试:

console.log('Before check')

await Car.findOne({ licensePlate }, (err, foundCar) => {
  if (err) return next(err)
  if (foundCar) return res.status(400).send('license plate exists already in db.')
})

console.log('After check')
// some other code, saving to db and stuff
return res.status(200).send('The car was saved succesfully.')

我天真的期望是,如果我在 Moongooses findOne 函数前面加上一个await关键字,那么“await block ”后面的代码将不会被执行,因为找到了一辆车,然后通过发送400响应来终止请求。相反,执行“await block ”之后的代码会导致

Error: Can't set headers after they are sent.

第二次尝试:

console.log('Before check')

try {
  const foundCar = await Car.findOne({ licensePlate })
  if (foundCar) return res.status(400).send('license plate exists already in db.')
} catch (err) {
  return next(err)
}

console.log('After check')
// some other code, saving to db and stuff
return res.status(200).send('The car was saved succesfully.')

这按预期工作,并防止任何代码在 if(foundCar) 检查后执行

问题:有人可以告诉我尝试一中发生了什么吗?现在来看,将回调与await关键字结合起来确实感觉很奇怪,但显然我对async/await的理解还不足以真正了解这里发生的情况。在这种情况下,await 是否意味着“代码等待”仅findOne 完成,然后回调和其余代码同时运行?任何指向有用资源以充分了解正在发生的事情的指针都将非常感激。

最佳答案

  1. 如果 findOne 函数未传递回调函数,它将返回一个 Promise 对象。
  2. 如果使用 Promise 对象调用 await,它将等待直到 Promise 解析该值并返回该值。
  3. 如果使用非 Promise 对象调用 await,它会将其转换为已解决的 Promise。

在第一种情况下,回调被传递给 findOne,因此它不会返回 Promise 对象,并且 await 将其转换为已解析的 Promise。它的值在 Node.js 执行周期的 nextTick 中解析。因此,这里不需要等待结果发生,甚至在调用回调函数之前发送响应 200。当回调实际执行时,它会尝试再次发送响应 header ,并且由于它们已经发送,因此您会收到此错误。

在第二种情况下,findOne 实际上返回一个 Promise 对象。因此 await 会等待 Promise 解析为一个值。这就是为什么第二种情况可以正常工作的原因。

关于node.js - 将回调传递给以await 为前缀的函数。执行顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48418344/

相关文章:

Node.js 按时间间隔同步 HTTP 客户端请求

Python Asyncio 任务在没有 gather() 的情况下运行

java - RabbitListener 不会接收使用 AsyncRabbitTemplate 发送的每条消息

javascript - 无法返回值以响应 mongoose/mongodb 和 nodejs

node.js - Mongoose - 枚举字符串数组

node.js - 为什么 NodeJS 核心模块没有 TypeScript 接口(interface)定义?

javascript - 检测系统范围的按键? ( Node .js?)

node.js - "Error: socket hang up"与 express

c - C中的异步通信

javascript - 使用 Mongoose 中间件改变请求正文