如何在数组的 forEach 循环中使用 promise 来填充对象

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

我是 运行 一个数组上的 forEach 循环并进行两次调用 return 承诺,我想填充一个对象说 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() 来避免在执行任何工作之前必须累积所有 Promise,而不是使用 Promise.all().

下面的代码是对sync使用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请求和return这些Promises的新数组。 我也使用了解构,但不确定我们在这里需要它。

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