Node.js和Mongoose的异步模式

时间:2014-04-02 02:55:41

标签: javascript node.js mongodb asynchronous mongoose

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

我在Mongoose文档中看到了这个例子:

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

然而,如果

product.save(...) 

执行得比

product.sold = Date.now()

在更新之前,你不会保存......? 也许我在这里遗漏了一些东西(在概念层面)?是什么让这段代码在异步环境中保持“安全”。

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

PS。我不是简单地使用 model.update 因为我需要验证。

2 个答案:

答案 0 :(得分:1)

异步并不意味着每条线都会同时执行。在这种情况下,product.sold将被分配并完成,就像正常操作一样,然后保存将在之后顺序调用。

异步部分与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. 回调有时会结束
  6. 因此,您更新产品并成功保存。您传递的匿名函数不是实际保存的函数,而是实现您想要的异步扩展,即处理错误或确保保存正确数量的项目。

答案 1 :(得分:0)

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

要了解阻塞(同步)和非阻塞(异步)操作之间的区别,请使用此基本异步代码:

function async(callback) {
  process.nextTick(callback);
}

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

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

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

但是,由于它不是(您可以从doc中看到,并且通常,该函数不接受任何回调参数的事实是一个很好的指示),该函数的执行将被阻止,直到该更新操作回报。