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

29

我正在使用axios promise库,但我认为我的问题更普遍。目前,我正在循环一些数据,并针对每个迭代执行单个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));

当我调用console.log时,mainObject还没有任何数据,因为axios仍在请求中。如何处理这种情况?

Axios确实有一个all方法和一个spread方法,但它们似乎只适用于预先知道要进行多少次调用的情况,而在我的情况下,我不知道会有多少遍循环。

1个回答

67

您需要将所有的 Promise 收集到一个数组中,然后使用 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/axios@0.19.2/dist/axios.min.js"></script>

axios文档中有描述(执行多个并发请求部分)。

在2020年5月之前,可以使用axios.all()实现此功能,但现已不建议使用


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接