在for循环中同步promises?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在for循环中同步promises?相关的知识,希望对你有一定的参考价值。
我坚持使用angularjs / javascript的这种异步执行。请帮忙
笔记
虚拟API用于示例目的。
那些Dummy API实际上是一个AngularJS服务。
我使用XmlHttpRequest进行演示,所以不需要讨论第三个参数是假还是真。
问题
在for循环中,调用calculateFormulaValue函数并基于参数,它将调用一些API并在承诺的对象中获取值。但是对于循环在promise对象返回之前完成,我无法在rowCollection中保存最终对象。
我们如何重构代码以获得所需的结果?
代码在这里 - > https://jsbin.com/xocisivuro/edit?js,console
码
var rowCollection = [];
var headerCollection = ["Formula 1", "Formula 2", "Formula 3", "Formula 4", "Formula 5", "Formula 6", "Formula 7"];
var currentFormulaValues = {};
//var finalCollection =
function generate(){
for(var i=0;i<headerCollection.length;i++){
calculateFormulaValue(i,headerCollection[i]);
console.log("current index" +i + " -->" +headerCollection[i]);
}
}
function calculateFormulaValue(j,currentFormula){
//Some common code which need to run ..
if(currentFormula == "Formula 1"){
var promise = new Promise(function(resolve, reject) {
var request = new XMLHttpRequest();
request.open('GET', 'https://api.icndb.com/jokes/random');
request.onload = function() {
if (request.status == 200) {
resolve(request.response);
} else {
reject(Error(request.statusText));
}
};
request.onerror = function() {reject(Error('Error fetching data.'));
};
request.send();
});
promise.then(function(data) {
currentFormulaValues[currentFormula] = JSON.parse(data).value.id;
//rowCollection[j] = JSON.parse(data).value.id;
console.log("j - " + j +" ->" + (JSON.stringify(currentFormulaValues)));
}, function(error) {
console.log('Promise rejected.');
});
}
else if(currentFormula == "Formula 2"){
var promise = new Promise(function(resolve, reject) {
var request = new XMLHttpRequest();
request.open('GET', 'https://api.icndb.com/jokes/random');
request.onload = function() {
if (request.status == 200) {
resolve(request.response);
} else {
reject(Error(request.statusText));
}
};
request.onerror = function() {reject(Error('Error fetching data.'));
};
request.send();
});
promise.then(function(data) {
currentFormulaValues[currentFormula] = JSON.parse(data).value.id;
//rowCollection[j] = JSON.parse(data).value.id;
console.log("j - " + j +" ->" + (JSON.stringify(currentFormulaValues)));
}, function(error) {
console.log('Promise rejected.');
});
}
// for all other formulas
else{
var promise = new Promise(function(resolve, reject) {
var request = new XMLHttpRequest();
request.open('GET', 'https://api.icndb.com/jokes/random');
request.onload = function() {
if (request.status == 200) {
resolve(request.response);
} else {
reject(Error(request.statusText));
}
};
request.onerror = function() {reject(Error('Error fetching data.'));
};
request.send();
});
promise.then(function(data) {
currentFormulaValues[currentFormula] = JSON.parse(data).value.id;
//rowCollection[j] = JSON.parse(data).value.id;
console.log("j - " + j +" ->" + (JSON.stringify(currentFormulaValues)));
}, function(error) {
console.log('Promise rejected.');
});
}
if(j == headerCollection.length-1){
console.log("SAVE FINAL")
rowCollection.push(currentFormulaValues);
console.log(JSON.stringify(currentFormulaValues))
}
}
当前输出
"current index0 -->Formula 1"
"current index1 -->Formula 2"
"current index2 -->Formula 3"
"current index3 -->Formula 4"
"current index4 -->Formula 5"
"current index5 -->Formula 6"
"SAVE FINAL"
"{}"
"current index6 -->Formula 7"
"j - 0 ->{"Formula 1":98}"
"j - 1 ->{"Formula 1":98,"Formula 2":175}"
"j - 2 ->{"Formula 1":98,"Formula 2":175,"Formula 3":523}"
"j - 3 ->{"Formula 1":98,"Formula 2":175,"Formula 3":523,"Formula 4":399}"
"j - 4 ->{"Formula 1":98,"Formula 2":175,"Formula 3":523,"Formula 4":399,"Formula 5":119}"
"j - 5 ->{"Formula 1":98,"Formula 2":175,"Formula 3":523,"Formula 4":399,"Formula 5":119,"Formula 6":261}"
"j - 6 ->{"Formula 1":98,"Formula 2":175,"Formula 3":523,"Formula 4":399,"Formula 5":119,"Formula 6":261,"Formula 7":164}"
预期输出
"current index0 -->Formula 1"
"j - 0 ->{"Formula 1":98}"
"current index1 -->Formula 2"
"j - 1 ->{"Formula 1":98,"Formula 2":175}"
"current index2 -->Formula 3"
"j - 2 ->{"Formula 1":98,"Formula 2":175,"Formula 3":523}"
"current index3 -->Formula 4"
"j - 3 ->{"Formula 1":98,"Formula 2":175,"Formula 3":523,"Formula 4":399}"
"current index4 -->Formula 5"
"j - 4 ->{"Formula 1":98,"Formula 2":175,"Formula 3":523,"Formula 4":399,"Formula 5":119}"
"current index5 -->Formula 6"
"j - 5 ->{"Formula 1":98,"Formula 2":175,"Formula 3":523,"Formula 4":399,"Formula 5":119,"Formula 6":261}"
"current index6 -->Formula 7"
"j - 6 ->{"Formula 1":98,"Formula 2":175,"Formula 3":523,"Formula 4":399,"Formula 5":119,"Formula 6":261,"Formula 7":164}"
//if j == headerCollection.length-1, then..
"SAVE FINAL" // then do ... rowCollection.push(currentFormulaValues);
任何有助于实现预期产出的帮助都会很好。提前致谢。
答案
您可以通过在此处输入return
关键字来返回您在calculateFormulaValue中创建的承诺:
return promise.then(function(data) { // ... etc
在你有这个结构的所有地方都这样做,以确保函数总是返回promise(甚至更好:尝试重用每个公式共同的代码 - 你有很多代码重复)。
然后你的主循环可以构建一个新数组,其中每个元素都是返回的promise:
var promises = headerCollection.map(function (collection, i) {
console.log("current index" +i);
// return(!) the promise you get from each call. This will become
// an element in a new array, returned by *map*.
return calculateFormulaValue(i, collection);
});
现在你可以等待所有的承诺与Promise.all
完成:
Promise.all(promises).then(function () {
// now your object is available.
});
注意:您应该进一步改进代码以避免使用全局变量,例如结果对象currentFormulaValues。
以上是关于在for循环中同步promises?的主要内容,如果未能解决你的问题,请参考以下文章