与 Node.js 和 Mongoose 的异步模式

Async Patterns with Node.js and Mongoose

本文关键字:异步 模式 Mongoose Node js      更新时间:2023-09-26

具体来说,我正在使用Mongoose和Node,但我想这是一个关于异步编码的概念性问题。

我在猫鼬文档中到处看到这个例子:

product.sold = Date.now();
product.save(function (err, product, numberAffected) {
  if (err) ..
})

但是,如果

product.save(...) 

执行速度快于

product.sold = Date.now()

您不会在更新之前保存吗...?也许我在这里错过了一些东西(在概念层面上)?是什么让这段代码在异步环境中保持"安全"。

更具体地说,我正在使用doc.addToSet作为"更新"步骤,如果它有一个回调,我可以嵌入doc.save步骤(以确保异步行为),我会感觉好多了。思潮?

附言。我不只是使用 model.update,因为我需要验证。

异步并不意味着

每一行同时执行。在这种情况下,product.sell 正在被分配并像正常操作一样完成,然后按顺序调用 save。

异步部分发生在 product.save 中。正在发生的事情是,您将一个函数作为参数传递给product.save,这也是一个函数。这称为匿名回调。它没有名称,从 product.save 内部异步调用。

以下是执行的顺序:

  1. Date.now() 被分配给 product.sold 并且操作完成
  2. product.save(callback(...){...})被调用
  3. product.save 到达回调并执行它,即 product.save 的定义中有一行说 callback.call(...) ,然后 product.save 返回
  4. 在 product.save 之后(您尚未列出)之后但在回调完成之前,下一行继续执行
  5. 回调在某个时间完成

因此,您更新产品并成功保存。您传递的匿名函数不是实际保存它的内容,而是一个异步扩展来执行您想要的操作,即处理错误或确保保存正确数量的项目。

您不必担心在保存之前发生更新操作,因为它会阻塞。

要了解阻塞(同步)和非阻塞(异步)操作之间的区别,请遵循以下基本异步代码:

function async(callback) {
  process.nextTick(callback);
}
async(function() {
  console.log('foo');
}
console.log('bar');

这将按顺序显示 bar ,然后foo 。这里的关键是函数 process.nextTick(cb) ,它会延迟回调的执行。

由于 NodeJS 只使用一个线程,它将等待整个函数堆栈返回,然后在进程的下一个循环中执行回调。现在,如果更新操作是异步的,则必须在传递给该操作的回调函数中执行保存操作。

但是,由于它不是(您可以从文档中看到这一点,并且通常,函数不接受任何回调参数的事实是一个很好的指示),因此在返回该更新操作之前,该函数的执行将被阻止。