我的 Node js 应用程序中有一个 for 循环;在此循环内,每次迭代都可以执行 mysql 查询(并非总是如此,具体取决于情况);查询是异步的,我在成功回调中得到结果;但我需要 for 循环的每次迭代都等待回调完成(如果需要):
function calculate() {
var resArray = [];
//[...]
for (i = 0; i < tables.length; i++) {
if (id !== undefined) {
var queryString = ... //build query
sequelize.query(queryString).success(function(result) { //executes query
id = result[0].id;
//do stuff with id returned by the query
//...
//resArray.push( //push in resArray the result of stuff done above )
});
}
else {
//do other kind of stuff and push result in resArray
}
}
return resArray;
}
如果 id != undefined,则执行查询,但 for 循环不会等待成功回调,并且函数返回不完整的 resArray。
我该如何做(或者如何重新组织代码)才能完成这项工作?
(我正在使用 Node js,但无法使用 jQuery)。
感谢 Amadan 的建议,我使用混合方法(使用 Promise 和 Counter)摆脱了这个问题;
我真的很想知道您对此的看法以及您是否有改进的建议;
首先,我向项目添加了 q 库(npm install q)以使用 Promise。
感谢 q 我已经能够将sequelize.query(基于回调)包装在返回承诺的函数中;
Promise 计数器在内存中保存仍待处理的 Promise 数量,并且当每个 Promise 得到解决时,包装函数executeQuery 会递减它;
(cycle()函数中的for循环执行4次循环;执行2次查询和2次简单日志;
目标是只有在 for 循环结束并且所有承诺都得到解决后,“完成”日志才会发送到屏幕
var id = req.params.id;
var counter = 0;
var endCycle = false;
var queryString = 'SELECT * FROM offers WHERE id = ' + id;
function query () {
var deferred = Q.defer();
sequelize.query(queryString).success(function(result) {
console.log('obtained result');
deferred.resolve(result);
});
return deferred.promise;
}
function executeQuery() {
query().then(function() {
console.log('after');
counter --;
console.log(counter);
finished();
});
}
function finished() {
if ((counter === 0) && (endCycle)) {
console.log('finished');
endCycle = false;
}
}
function cycle() {
var result;
for (i = 0; i <= 3; i ++) {
if (i > 1) {
counter ++;
executeQuery();
}
else {
console.log('else');
}
}
endCycle = true;
finished();
}
cycle();
- - - - - - - - - 更新 - - - - - - - - - - - - - - - - ----------------------------
根据hugomg的建议,我用更干净的代码更新了代码:
我将每个承诺推送到一个数组中,然后使用 Q.all 等待所有承诺都得到解决
var id = req.params.id;
var promisesArray = [];
var endCycle = false;
var queryString = 'SELECT * FROM offers WHERE id = ' + id;
function query () {
var deferred = Q.defer();
sequelize.query(queryString).success(function(result) {
console.log('obtained result');
deferred.resolve(result);
finished();
});
promisesArray.push(deferred.promise);
}
function finished() {
if (endCycle) {
endCycle = false;
Q.all(promisesArray).then(function() {
console.log('finished');
});
}
}
function cycle() {
var result;
for (i = 0; i <= 3; i ++) {
if (i > 1) {
query();
}
else {
console.log('else');
}
}
endCycle = true;
finished();
}
cycle();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)