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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38362231/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:22:51  来源:igfitidea点击:

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

javascriptarraysforeachpromisees6-promise

提问by rond

I am running a forEach loop on an array and making two calls which return promises, and I want to populate an object say this.options, and then do other stuff with it. Right now I am running into the async issue if i use the following code sample and i get into the then function first.

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

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

This is working code below, but it only works for the first element in the array, because I call the resulting function in the .thenof the response. I want to do all the fetch first for all elements of the array and then call the resulting function to do something.

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

How do i populate the self.filesobject after the forEach loop is complete, and then call the resulting function with the files object?

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

回答by Timo

Promise.all()will be helpful here:

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

This starts the AJAX call for each of the items, adds the result of each call to self.filesonce the call is complete and calls self.resultingFunction()after all calls have been completed.

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

Edit:Simplified based on Yury Tarabanko's suggestions.

编辑:根据 Yury Tarabanko 的建议进行简化。

回答by IonicBurger

Just a slight variation of the accepted solution above would be:

上面接受的解决方案的一个轻微变化是:

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

I used Array.mapinstead of Array.forEach, which means I don't need to create an empty array first, I just re-use the existing one.

我使用了Array.map而不是Array.forEach,这意味着我不需要先创建一个空数组,我只是重新使用现有的数组。

回答by Alan Mimms

You might look at this answer to a similar questionfor an excellent hint. The solution given there uses Array#reduce()to avoid having to accumulate all of the Promises before doing any of the work rather than using Promise.all().

您可以查看类似问题的答案以获得极好的提示。那里给出的解决方案Array#reduce()用于避免在执行任何工作之前必须累积所有 Promises 而不是使用Promise.all().

回答by jasmeetsohal

The following code is simple understanding of sync using Promise.

下面的代码是对使用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);    
  })

 });

Above example will hold array numsfor 5 sec. and it will print on console after it release.

上面的示例将保存数组 nums5 秒。它会在发布后打印在控制台上。