簡體   English   中英

如何在數組的 forEach 循環中使用 promise 來填充對象

[英]How to use promise in forEach loop of array to populate an object

我在數組上運行 forEach 循環並進行兩次返回承諾的調用,我想填充一個對象 say this.options ,然后用它做其他事情。 現在,如果我使用以下代碼示例並首先進入 then 函數,我就會遇到異步問題。

$.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對象,然后使用 files 對象調用結果函數?

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 的建議進行簡化。

上面接受的解決方案的一個輕微變化是:

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

我使用Array.map而不是Array.forEach ,這意味着我不需要先創建一個空數組,我只需重新使用現有的數組。

您可以查看類似問題的答案以獲得極好的提示。 那里給出的解決方案使用Array#reduce()來避免在執行任何工作之前必須累積所有 Promises 而不是使用Promise.all()

下面的代碼是對使用Promise進行同步的簡單理解。

let numArr = [1,2,3,4,5];
let nums=[];

let promiseList = new Promise(function(resolve,reject){
  setTimeout(()=>{
        numArr.forEach((val)=>{
        nums.push(val);
    });
    resolve(nums);
 },5000)
})


Promise.all([promiseList]).then((arrList)=>{
  arrList.forEach((array)=>{
    console.log("Array return from promiseList object ",array);    
  })

 });

上面的示例將保存數組nums 5 秒。 它會在發布后打印在控制台上。

您可以使用.map作為一個循環,為數組的每個元素啟動 Promise 請求,並返回這些 Promise 的新 Array。 我也使用了解構,但不確定我們在這里是否需要它。

await Promise.all([...arr.map(i => "our promise func"())]);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM