如何使循环等待node.js中的callback?

我有情景。 我想在mongodb中更新数据后执行循环。 意思就是这样:

var i = 0; while (i< 5) { attendanceDataModel.update(query, condition).exec(function(error, data) { if (error) { console.log("Error @ 168 line in app.js File : \n" + err + "\n"); i++; } else { if (data.length <= 0) { console.log("No Records Matched."); i++; } else { console.log(currEmpId + " : successfully Logged Out ! :-)" + data + "\n"); updateRecordNumber(currRecordNumber); i++; //wrong because it increases the value before updating in DB. } } }); } var updateRecordNumber = function(currRecordNumber) { var condition = { deviceLogId: parseInt(currRecordNumber) }; lastDeviceLogIdModel.update({}, condition).exec(function(error, data) { if (error) { console.log("Error @ 213 line in app.js File : \n" + err + "\n"); } else { if (data.length <= 0) { console.log("No Records Matched." + "\n"); } else { console.log(currRecordNumber + " : DeviceLogId successfully Updated ! :-)"); // I want to increase value of i here after updation in database } } }); } 

现在,我想在函数updateRecordNumber成功更新之后增加variablesi的值

最简单的方法就是var updateRecordNumber = function(currRecordNumber, callback) ,然后更改调用: updateRecordNumber(currRecordNumber, function(){ i++ });

但我认为这是一个更好的解决scheme,使用一些控制stream的方法,例如Promises或Async.js

PS当然你必须改变function的身体:

 var updateRecordNumber = function(currRecordNumber, callback) { // all your async stuff callback(); } 

代码可以更改为:

 var i = 0; function startUpdation() { return attendanceDataModel.update(query, condition).exec(function(error, data) { if (error) { console.log("Error @ 168 line in app.js File : \n" + err + "\n"); i++; if (i<5) { return startUpdation(); } return; } else { if (data.length <= 0) { console.log("No Records Matched."); i++; if (i<5) { return startUpdation(); } return; } else { console.log(currEmpId + " : successfully Logged Out ! :-)" + data + "\n"); return updateRecordNumber(currRecordNumber).then(function (err, data){ i++; if (i<5) { return startUpdation(); } return; }); } } }); } function updateRecordNumber (currRecordNumber) { var condition = { deviceLogId: parseInt(currRecordNumber) }; return lastDeviceLogIdModel.update({}, condition).exec(function(error, data) { if (error) { console.log("Error @ 213 line in app.js File : \n" + err + "\n"); } else { if (data.length <= 0) { console.log("No Records Matched." + "\n"); } else { console.log(currRecordNumber + " : DeviceLogId successfully Updated ! :-)"); } } }); } startUpdation(); 

请尝试这个解决scheme。

如果你提交函数updateRecordNumber,并在then()中写入增量调用会更好。

你的while循环是同步的,并不考虑对数据库操作的响应有时候会返回。 您需要通过recursion重新计划操作(5次尝试后退出),在不必要的操作之后重新查询:

 function execute(count, callback) { if (count == 5) { return callback(new Error('meh...')) } loadSomethingAsync(function(error, result) { if (error || !result) { return execute(count++, callback) } callback(null, result) }) } execute(0, function(error, result) { if (error) { return console.log('after 5 tries still no result or error...') } console.log('yay, async op has finished!') }) 

如何重构循环自身是callback的一部分? 像这样的东西:

 var i = 0, fna = function (error, data) { if (error) { console.log("Error @ 168 line in app.js File : \n" + err + "\n"); fnc(); //i++; } else { if (data.length <= 0) { console.log("No Records Matched."); fnc(); //i++; } else { console.log(currEmpId + " : successfully Logged Out ! :-)" + data + "\n"); updateRecordNumber(currRecordNumber); //i++; //wrong because it increases the value before updating in DB. } } }, updateRecordNumber = function (currRecordNumber) { var condition = { deviceLogId : parseInt(currRecordNumber, 10) }; lastDeviceLogIdModel.update({}, condition).exec(fnb); }, fnb = function (error, data) { if (error) { console.log("Error @ 213 line in app.js File : \n" + err + "\n"); } else { if (data.length <= 0) { console.log("No Records Matched." + "\n"); } else { console.log(currRecordNumber + " : DeviceLogId successfully Updated ! :-)"); // I want to increase value of i here after updation in database fnc(); } } }, fnc = function () { i++; if (i < 5) { attendanceDataModel.update(query, condition).exec(fna); } }; attendanceDataModel.update(query, condition).exec(fna); 

您可以在节点js中使用同步模块。您可以在这里看到我的博客input链接描述