Node.js – asynchronous虽然循环不迭代

根据以前的问题非法break语句(Node.js)的build议 ,我实现了async.whilst() ,但是它不会迭代多次。

我试图find一个唯一的ID,在一个ID的末尾增加一个数字,然后查询Mongo来查看该ID是否存在。 如果不存在,则find唯一的ID。 它只循环一次,而不是直到find一个唯一的。 哪里不对?

代码:

  var uniqueNumber = 1; var newUnique; async.whilst( function () { var uniqueNum_string = uniqueNumber.toString(); newUnique = data.id + uniqueNum_string; db.collection('landmarks').findOne({'id':newUnique}, function(err, data){ if (data){ console.log('entry found!'); return; } else { console.log('entry not found!'); } }); }, function (callback) { uniqueNumber++; }, function (err) { saveLandmark(newUnique); } ); 

我实际上找不到一个适合这个任务的良好的asynchronous函数,所以我使用async.forever()方法攻击了一些东西。 该函数将继续运行,直到你callback一个“错误”,这是你想要做的。

 var uniqueNumber = 1; var newUnique; async.forever(function (next) { var uniqueNum_string = uniqueNumber.toString(); newUnique = data.id + uniqueNum_string; db.collection('landmarks').findOne({'id':newUnique}, function(err, data){ if (data){ console.log('entry found!'); uniqueNumber++; next(); } else { console.log('entry not found!'); next('unique!'); // This is where the looping is stopped } }); }, function () { saveLandmark(newUnique); }); 

关于你想要解决的问题,在我看来,你想插入一个具有唯一ID的新文件。 如果是这样,你会经常这样做,我会说这是一个非常低效的方法。 如果数据库中有一千个文档,那么在你接近唯一标识之前,你会对数据库做一千个完全没有意义的请求。

更好的方法是从集合中获取sorting的第一个文档(例如最高的id)。 然后增加一个id并尝试插入,直到它不被拒绝。 因为即使find唯一的ID,在保存文档时,另一个插入可能是由另一个客户端或另一个实例(在负载平衡的情况下)创build的。 这可能是也可能不是你的问题,我不太了解你的应用程序,我只是认为你应该知道你目前的做法和我的答案的缺点。

像这样的东西? 我没有testing它,因为我不知道你使用的是哪个数据库模块,但逻辑应该是显而易见的。

 function searchNubmersForResults(firstNumber, callback) { //place other variables here, and you can collect the results within the closure, and send them as arguments to your callback function testNumber(uniqueNumber) { var uniqueNum_string = uniqueNumber.toString(); newUnique = data.id + uniqueNum_string; db.collection('landmarks').findOne({'id':newUnique}, function(err, data){ if (data){ console.log('entry found!'); callback(data);//We're done, use the callback on the data } else { console.log('entry not found!'); testNumber(uniqueNumber++);//Launch the next test } }); } testNumber(firstNumber);//Laucn the first test } searchNubmersForResults(0, function(data) { console.log('You have data now: ' + data); });