问题
Hello I'm new to Javascript and APIs.
But I have an excersise where I should get Data from.
https://swapi.co/api/planets/
The problem is that it doesn't list all the planets at once so that URL only shows the first 10 entries while https://swapi.co/api/planets/?page=2 shows the next and so on.
This is my current code, it works but I don't think I'm going as I'm supposed to so I wonder how you would solve this problem.
https://codepen.io/indiehjaerta/pen/QQXVJX
var starWarsAPI = new StarWarsAPI();
starWarsAPI.Initialize();
function StarWarsAPI()
{
    this.planets = new Array();
    this.Initialize = function()
    {
        this.LoadPlanets("https://swapi.co/api/planets");
    }
    this.LoadPlanets = function(aURL)
    {
        fetch(aURL).then(
            function (response) 
            {
                if (response.status !== 200) 
                {
                    console.log('Looks like there was a problem. Status Code: ' + response.status);
                    return;
                }
                response.json().then(
                    data => this.LoadPlanetsRecursive(data)
                );
            }.bind(this)
        ).catch(function (err) 
        {
            console.log('Fetch Error :-S', err);
        });
    }
    
    this.LoadPlanetsRecursive = function(aData)
    {
        for (let planet of aData.results)
        {
            let newPlanet = new Planet(planet);
            this.planets.push(newPlanet);
        }
        if (aData.next != null)
        {
            fetch(aData.next).then(
                function (response) 
                {
                    if (response.status !== 200) 
                    {
                        console.log('Looks like there was a problem. Status Code: ' + response.status);
                        return;
                    }
    
                    response.json().then(
                        data => this.LoadPlanetsRecursive(data)
                    );
                }.bind(this)
            ).catch(function (err) 
            {
                console.log('Fetch Error :-S', err);
            });
        }
    }
this.PresentPlanetsInHTML = function()
{
    
}
}
function Planet(aPlanet)
{
    this.name = aPlanet.name;
    console.log(this);
}
2nd question is where I should put my "PresentData" so I know that all planets have been loaded and not 1 by 1 when the're added to the array.
回答1:
You could recursively create a promise resolve chain. A bit less repetition and you'll know when all planets are loaded when the parent promise resolves.
function getStarWarsPlanets(progress, url = 'https://swapi.co/api/planets', planets = []) {
  return new Promise((resolve, reject) => fetch(url)
    .then(response => {
        if (response.status !== 200)  {
          throw `${response.status}: ${response.statusText}`;
        }
        response.json().then(data => { 
          planets = planets.concat(data.results);
          if(data.next) {
            progress && progress(planets);
            getStarWarsPlanets(progress, data.next, planets).then(resolve).catch(reject)
          } else {
            resolve(planets);
          }
        }).catch(reject);
    }).catch(reject));
}
function progressCallback(planets) {
  // render progress
  console.log(`${planets.length} loaded`);
}
getStarWarsPlanets(progressCallback)
  .then(planets => {
    // all planets have been loaded
    console.log(planets.map(p => p.name))
  })
  .catch(console.error);
    回答2:
I had similar needs so I wrote a library called fetch-paginate - here's an example: https://codepen.io/AndersDJohnson/pen/Jqadoz
fetchPaginate.default("https://swapi.co/api/planets", {
  items: page => page.results,
  params: true
})
.then(res => {
  res.data.forEach(planet => {
    const newPlanet = new Planet(planet);
    this.planets.push(newPlanet);
  })
})
You can get it here: https://unpkg.com/fetch-paginate@3.0.1/bundle.js
来源:https://stackoverflow.com/questions/49129245/javascript-using-fetch-and-pagination-recursive