简体   繁体   中英

Chained fetches dependent on each other

Take the following scenario:

I need to show in a table a list with all countries and the population of each country. All data can be queried from here: api.population.io.

Thare are 2 api calls that can help me achieve what i want:

  1. http://api.population.io:80/1.0/countries - returns a list of all existing countries
  2. http://api.population.io:80/1.0/population/ {$country}/today-and-tomorrow/ - returns the population of a particular country

As you can see i need to make 2 api calls since the second call is dependant of the name of the country made by the first call. I managed to make it work with the initial api call using fetch by using this code:

    fetch('http://api.population.io:80/1.0/countries')
    .then(results => {
        return results.json();
    }).then(data => {
        //data.countries
    })

This just returns me a list with all the countries.

Now i need to loop through data.countries and make a new api call for each country without breaking the whole process. I tried throwing another fetch call where data.countries is available while looping over data.countries but as you can imagine this breaks up the whole process, what i think happens is that the loop doesn't wait for the fetch call to complete thus messing up the query process.

I'm pretty new to this and i've tried googling it but i'm not sure what i can use to achieve what i need. Any help would be truly appreciated. I've been dealing with this problem the whole day

You could fire all the separate population requests at once and use the result when all of them have finished, with the help of Promise.all :

fetch("http://api.population.io:80/1.0/countries")
  .then(results => {
    return results.json();
  })
  .then(data => {
    const populationPromises = data.countries.map(country => {
      return fetch(
        `http://api.population.io:80/1.0/population/${country}/today-and-tomorrow/`
      ).then(results => results.json());
    });

    return Promise.all(populationPromises);
  })
  .then(populations => {
    console.log(populations);
  })
  .catch(error => {
    console.error(error);
  });

The approach with async/await makes the code more coherent and readable:

function getCountries() {
    return fetch('http://api.population.io/1.0/countries/?format=json').then(s => s.json())
}

function getPopulation(country) {
    return fetch(encodeURI(`http://api.population.io:80/1.0/population/${country}/today-and-tomorrow/?format=json`)).then(s => s.json())
}

(async () => {

    try {

        const { countries } = await getCountries();
        const populations = await Promise.all(countries.map(getPopulation));

        console.log(populations);

    } catch(err) {
        console.log(err);
    }

})();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM