Javascript 等待循环中调用的所有承诺完成

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37213783/
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 20:02:39  来源:igfitidea点击:

Waiting for all promises called in a loop to finish

javascriptpromiseaxios

提问by jkj2000

I'm using the axiospromise library, but my question applies more generally I think. Right now I'm looping over some data and making a single REST call per iteration.
As each call completes I need to add the return value to an object. At a high level, it looks like this:

我正在使用axios承诺库,但我认为我的问题更普遍。现在我正在遍历一些数据并在每次迭代中进行一次 REST 调用。
随着每次调用完成,我需要将返回值添加到一个对象中。在高层次上,它看起来像这样:

var mainObject = {};

myArrayOfData.forEach(function(singleElement){
  myUrl = singleElement.webAddress;
  axios.get(myUrl)
  .then(function(response) {
    mainObject[response.identifier] = response.value;
   });
});

console.log(convertToStringValue(mainObject));

What's happening of course is when I call console.logthe mainObjectdoesn't have any data in it yet, since axios is still reaching out. What's a good way of dealing with this situation?

这是怎么回事,当然是当我打电话console.logmainObject没有在其任何数据,因为爱可信还是伸手。处理这种情况的好方法是什么?

Axios does have an allmethod along with a sister spreadone, but they appear to be of use if you know ahead of time how many calls you'll be making, whereas in my case I don't know how many loop iterations there will be.

Axios 确实有一个all方法和一个姊妹方法spread,但是如果您提前知道要进行多少次调用,它们似乎很有用,而在我的情况下,我不知道会有多少次循环迭代。

回答by krasu

You need to collect all of your promises in an array and then use Promise.all:

您需要将所有承诺收集在一个数组中,然后使用Promise.all

// Example of gathering latest Stack Exchange questions across multiple sites
// Helpers for example
const apiUrl = 'https://api.stackexchange.com/2.2/questions?pagesize=1&order=desc&sort=activity&site=',
    sites = ['stackoverflow', 'ubuntu', 'superuser'],
    myArrayOfData = sites.map(function (site) {
        return {webAddress: apiUrl + site};
    });

function convertToStringValue(obj) {
    return JSON.stringify(obj, null, '\t');
}

// Original question code
let mainObject = {},
    promises = [];

myArrayOfData.forEach(function (singleElement) {
    const myUrl = singleElement.webAddress;
    promises.push(axios.get(myUrl));
});

Promise.all(promises).then(function (results) {
    results.forEach(function (response) {
        const question = response.data.items[0];
        mainObject[question.question_id] = {
            title: question.title,
            link: question.link
        };
    });

    console.log(convertToStringValue(mainObject));
});
<script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script>

It's described in axios docs(Performing multiple concurrent requests section).

它在axios 文档(执行多个并发请求部分)中进行了描述。

Before May 2020 it was possible to do with axios.all(), which is now deprecated.

在 2020 年 5 月之前,可以使用 axios.all(),现在已弃用