2016-07-13 124 views
7

我正在數組上運行forEach循環,並進行兩個返回承諾的調用,並且我想填充一個對象,如this.options,然後用它來做其他事情。現在我遇到了異步問題,如果我使用下面的代碼示例,我首先進入then函數。如何在forEach循環中使用promise來填充對象

$.when.apply($, someArray.map(function(item) { 
    return $.ajax({...}).then(function(data){...}); 
})).then(function() { 
    // all ajax calls done now 
}); 

這在下面工作的代碼,但它僅適用於所述陣列中的第一個元素,因爲我調用的響應的.then所得到的函數。我想先爲數組的所有元素執行所有的提取操作,然後調用結果函數來執行某些操作。

array.forEach(function(element) { 
    return developer.getResources(element) 
     .then((data) = > { 
      name = data.items[0]; 
      return developer.getResourceContent(element, file); 
     }) 
     .then((response) = > { 
      fileContent = atob(response.content); 
      self.files.push({ 
       fileName: fileName, 
       fileType: fileType, 
       content: fileContent 
      }); 
      self.resultingFunction(self.files) 
     }).catch ((error) = > { 
      console.log('Error: ', error); 
     }) 
}); 

我如何填充foreach循環後的self.files對象是完整的,然後調用與文件生成的函數對象?

+0

爲什麼'forEach'當你明確需要'map'? –

+0

@YuryTarabanko我使用了一張地圖,但也沒有工作。我也在答案中嘗試了這種方法,但是使用'.when.apply($,promise).then()',但也沒有工作。我認爲這是行不通的,因爲我沒有這樣做ES6的方式。 – rond

回答

20

Promise.all()將有助於在這裏:​​

var promises = []; 

array.forEach(function(element) { 
    promises.push(
     developer.getResources(element) 
      .then((data) = > { 
       name = data.items[0]; 
       return developer.getResourceContent(element, file); 
      }) 
      .then((response) = > { 
       fileContent = atob(response.content); 
       self.files.push({ 
        fileName: fileName, 
        fileType: fileType, 
        content: fileContent 
       }); 
      }).catch ((error) = > { 
       console.log('Error: ', error); 
      }) 
    ); 
}); 

Promise.all(promises).then(() => 
    self.resultingFunction(self.files) 
); 

這將啓動AJAX調用的每個項目,將每個呼叫self.files的結果,一旦通話結束,所有的呼叫都完成後調用self.resultingFunction()

編輯:根據Yury Tarabanko的建議進行簡化。

+0

應該是'Promise.all',而不是Promises(複數)。 – lucasjackson

+0

@lucasjackson好的,謝謝! – Timo

+0

你爲什麼手動創建Promise?它看起來像'getResources'已經返回一個 –

3

剛剛接受的解決方案的輕微變化上面會:

var promises = array.map(function(element) { 
     return developer.getResources(element) 
      .then((data) = > { 
       name = data.items[0]; 
       return developer.getResourceContent(element, file); 
      }) 
      .then((response) = > { 
       fileContent = atob(response.content); 
       self.files.push({ 
        fileName: fileName, 
        fileType: fileType, 
        content: fileContent 
       }); 
      }).catch ((error) = > { 
       console.log('Error: ', error); 
      }) 
}); 

Promise.all(promises).then(() => 
    self.resultingFunction(self.files) 
); 
0

你可能看this answer to a similar question一個極好的提示。鑑於有該解決方案採用Array#reduce(),以避免做任何工作,而不是使用Promise.all()之前積累的所有承諾。