2016-12-25 4 views
2

Я застрял в этом асинхронном выполнении angularjs/javascript. Пожалуйста, помогитесинхронизировать обещания внутри цикла?

ПРИМЕЧАНИЯ

пустышка API, используемый для образца цели.

Эти Dummy API действительно являются сервисом AnugularJS в режиме реального времени.

Я использовал XmlHttpRequest для демонстрационной цели, поэтому нет необходимости обсуждать третий аргумент как ложный или истинный.

ПРОБЛЕМА

Внутри цикл, функция calculateFormulaValue называются и на основании аргумента, он будет вызывать некоторые API и получить значение в обетованном объекте. Но для цикла завершается, пока объект обещания не возвращается, и я не могу сохранить конечный объект в 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 OUTPUT

"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); 

Любая помощь в достижении ожидаемого результата будет хорошей. Заранее спасибо.

ответ

3

Вы можете вернуть обещание, что вы создаете в calculateFormulaValue, поставив return ключевое слово здесь:

return promise.then(function(data) { // ... etc 

ли это во всех местах, где вы имеете такую ​​конструкцию, чтобы убедиться, что функция всегда возвращает обещание (или даже лучше: попытайтесь повторно использовать код, общий для каждой формулы - у вас много дублирования кода там).

Тогда ваш основной цикл может создать новый массив, где каждый элемент является возвращаемым обещание:

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. 
}); 

NB: вам следует улучшить код, чтобы избежать использования глобальных переменных, таких как объект результата currentFormulaValues ​​.

+0

Perfect. Спасибо за ваши короткие и хрустящие советы и заметки. Working Fiddle [link] (https://jsbin.com/pucumemumo/edit?js,console) – Zing14

Смежные вопросы