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

ron*_*ond 22 javascript arrays foreach promise es6-promise

我在一个数组上运行一个forEach循环并进行两次返回promises的调用,我想填充一个对象说this.options,然后用它做其他的事情.现在我遇到异步问题,如果我使用下面的代码示例,我首先进入then函数.

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

这是下面的工作代码,但它只适用于数组中的第一个元素,因为我.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);
        })
});
Run Code Online (Sandbox Code Playgroud)

如何self.files在forEach循环完成后填充对象,然后使用files对象调用生成的函数?

Tim*_*imo 64

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)
);
Run Code Online (Sandbox Code Playgroud)

这将启动每个项目的AJAX调用,self.files在调用完成self.resultingFunction()后将每个调用的结果添加到所有调用完成后调用.

编辑:基于Yury Tarabanko的建议简化.

  • 应该是`Promise.all`,而不是Promises(复数)。 (2认同)
  • 为什么要手动创建Promise?看起来`getResources`已经返回一个 (2认同)

Ion*_*ger 22

只是上面接受的解决方案的一个小变化将是:

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)
);
Run Code Online (Sandbox Code Playgroud)

  • 在最后添加了一个新句子来解释我做了什么。 (4认同)

let*_*ser 9

您可以使用.map一个循环来为数组的每个元素启动 Promise 请求并返回这些 Promise 的新数组。我还使用了解构,但不确定我们是否需要它。

await Promise.all([...arr.map(i => "our promise func"())]);
Run Code Online (Sandbox Code Playgroud)