Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/432.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何避免Nodejs和Mongoose应用程序中的竞争条件?_Javascript_Node.js_Mongodb_Mongoose - Fatal编程技术网

Javascript 如何避免Nodejs和Mongoose应用程序中的竞争条件?

Javascript 如何避免Nodejs和Mongoose应用程序中的竞争条件?,javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,我有一个例程来更新数据库中的一个值,然后在一秒钟的计时器上查找它。这里是一个简单的设置 function checkStatusAndDoWork(){ userMongooseModel.find({'someCondition': { $gte:(new Date()) }}, function(err, userModel){ if (userModel.length > 0) { //there is only one document in the return.

我有一个例程来更新数据库中的一个值,然后在一秒钟的计时器上查找它。这里是一个简单的设置

function checkStatusAndDoWork(){
  userMongooseModel.find({'someCondition': { $gte:(new Date()) }}, function(err, userModel){
      if (userModel.length > 0) { //there is only one document in the return.
          doSomeWorkThatTakes20seconds();
          // Update the Mongo document with a new next time
          userMongooseModel.update( {_id:userModel[0]._id}, {'someCondition': Date.now() + 10000}, function(err, numAffected){ 
              console.log('Checkpoint 1'); 
              setTimeout(checkStatusAndDoWork, 1000); //repeat the loop after 1 second.
          })
      } else {
          console.log('Checkpoint 2');
          setTimeout(checkStatusAndDoWork, 1000); // otherwise repeat the loop after 1 second anyways.
      }
  }
}
情况-

正常情况下,一切正常。我看到以下情况:

Checkpoint 1
Checkpoint 2
Checkpoint 2
...
Checkpoint 2
Checkpoint 1
Checkpoint 2
Checkpoint 2
...
但是,如果我打开MongoExplorer并开始查看文档,那么如果我恰好对它进行了调整,我会看到以下内容

Checkpoint 1
Checkpoint 2
Checkpoint 2
...
Checkpoint 2
Checkpoint 1
Checkpoint 1
Checkpoint 1
Checkpoint 1
Checkpoint 1
Checkpoint 2
Checkpoint 2
...
似乎更新进入了Mongo队列,因此文档不会立即更新。这会导致find()返回true并重复转到“检查点1”,直到db写入完成

我怎样才能避免这种比赛状态


注意:为了简化,我重写了这个问题。

您的
函数是同步的还是异步的?在日志中插入时间戳可能会有所帮助。无论
doSomeWorkThatTakes20Secs()
是同步还是异步,如果在
userMongooseModel之后执行。update
可能会阻止JS执行线程20秒,因此
someCondition
在下一次
checkStatusAndDoWork
时仍然有效,理论上应该在1秒后执行,但由于事件循环被阻塞,它会在21秒后执行。您能否尝试将花费20秒的
dosomework拆分为一系列较小的任务?您不应该长时间阻止事件循环。在浏览器中,这通常是通过递归的
setTimeout
调用来解决的,但我知道在Node.JS中有
process.nextTick
或类似的更快的调用。我完全删除了dsosomeworkhatstakes20secs(),并将其替换为对一些数学函数的伪调用:var randomNum=math.floor(math.random()*60*0.6) + 60*0.4; var waitTimeout=randomNum*10*1000;只是为了好玩。没有变化。您更换了它,新功能是否也会阻止执行20秒?问题是-你能完全删除它还是以非阻塞的方式重写它?