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秒?问题是-你能完全删除它还是以非阻塞的方式重写它?