我如何等待for循环进入下一个循环?
如何确保执行userdetails并在传递新变量之前将realresult.playername分配给新变量?
代码:
return new Promise( function (resolve, reject) {
arr = [];
messages.find({convid: convid}).then(function(result) {
for(var a in result) {
realresult = result[a];
userData.userDetails(realresult.userid).then(function (result) {
realresult.playername = result.username;
});
userData.usercashinfo(realresult.userid).then(function (resulttwo) {
realresult.playerdetails = resulttwo;
});
arr.push(realresult);
}
return resolve(arr);
});
});
答案 0 :(得分:1)
您正在尝试编写一个承诺,当它结算时,返回已解析的承诺值数组。你应该在这里做两件事:
return
等待承诺的完成。在承诺链中,除非是return
,否则实际上没有任何内容可以解析承诺值。 (您也应该将此用于message.find()
,因为它也会给您一个承诺。)Promise.all()
收集承诺对象 - all()
仅在传递给它的所有承诺都已解决后才返回。result
变量名来表示多个内容。这里没有错,但它可能导致不必要的混淆。放在一起,这看起来像是:
return messages.find(...).then(function(result) {
var promiseArr = [];
for (var a in result) {
promiseArr.push(
promise.all([userData.userDetails(...), userData.usercashinfo(...)])
.then(function(detailinfo) {
var realresult = result[a];
var details = detailinfo[0];
var cashinfo = detailinfo[1];
realresult.playername = details.username;
realresult.playerdetails = cashinfo;
return realresult;
});
}
return Promise.all(promiseArr);
});
答案 1 :(得分:0)
所以我认为尝试使用生成器和承诺来解决它是一个好主意,我不确定它是最好的方法,但它是两者结合的好习惯所以我试一试。
这个想法是生成器函数在开始新的迭代之前等待回调函数,并且回调函数在告诉生成器函数继续迭代之前等待两个promise完成。
here is a more simple example that I first tried on codepen
return new Promise( function (resolve, reject) {
arr = [];
messages.find({convid: convid}).then(function(result) {
function* iterations() {
for (var i = 0; i < result.length; i++) {
realresult = result[i];
try {
var cbResult = yield cb(result[i].userid);
realresult.playername = cbResult.playername;
realresult.playerdetails = cbResult.playerdetails;
arr.push(realresult);
} catch (e) { reject(e) }
}
return arr.value;
}
var it = iterations();
it.next();
function cb(userid) {
Promise.all([
userData.userDetails(userid),
userData.usercashinfo(userid)
]).then(
function(values) {
var realresult = {playername : values[0], playerdetails : values[1]}
returnValue = it.next(realresult);
if (returnValue.done) {
resolve(returnValue);
}
},
function(e) { reject(e) }
);
}
});
});