Home > Software engineering >  JavaScript, fetch, API
JavaScript, fetch, API

Time:06-20

i want to do the following: get a random name with fetch from this website https://swapi.dev/api/people/, which i did and i can see it in my html page then i want also to get a random planet, here i need to access the homeworld key, and to return the link, before returning the link i formatted to get a random url and from this one i also have to show the name of the planet on my page. The first fetch works fine, at least i think but the 3rd .then() is not working or at least i don't know how to access the information from the homeworld url. This is my first time trying fetch() and it will be nice if you guys can help me telling where i did wrong in code and maybe different solutions but not so complicated :D tnks

let randomNumber = Math.floor(Math.random()*9)


const fetchPromise = fetch("https://swapi.dev/api/people/");

let test
let test2
let planets = document.querySelector('#age')
fetchPromise
    .then((response) => {
        if (!response.ok) {
            throw new Error(`Http error: ${response.status}`);

        }
        return response.json();
    })
    .then((json) => {
        console.log(json.results[randomNumber].name)
        showRandomUserData(json)
        test = json.results[0].homeworld
        test = test.slice(0, -2)
        // console.log(test   randomNumber   "/");
        // console.log(test   "/"   randomNumber   "/");
        test = test   randomNumber   "/";
        return fetch(test)
        // return fetch("https://swapi.dev/api/planets/2/");
    })
    .then(response => response.json()).then(json =>
    {   test2=json.name
        console.log(test2);
        planets.innerHTML = test2
    }) 

showRandomUserData = (randomUser) => {
    document.querySelector("#name").innerHTML =
        randomUser.results[randomNumber].name;

}


Solved

CodePudding user response:

Here's a simple solution that uses fetch() to grab data from both those URLs and then insert all the people and the one planet that is returned into your web page:

function myFetch(...args) {
    return fetch(...args).then(response => {
        if (!response.ok) {
            throw new Error(`fetch failed with status ${response.status}`);
        }
        return response.json();
    });
}

Promise.all([
    myFetch("https://swapi.dev/api/people/"),
    myFetch("https://swapi.dev/api/planets/2/")
]).then(([people, planet]) => {
    const peopleDiv = document.getElementById("people");
    let peopleHTML = "";
    for (let p of people.results) {
        peopleHTML  = `<div>${p.name}</div>`;
    }
    peopleDiv.innerHTML = peopleHTML;
    
    const planetDiv = document.getElementById("planets");
    let planetHTML = `<div>${planet.name}</div>`;
    planetDiv.innerHTML = planetHTML;
}).catch(err => {
    console.log(err);
});
<div id="people"></div>
<hr>
<div id="planets"></div>

As for using the results, the people URL returns a structure that looks like this:

{
  count: 82,
  next: 'https://swapi.dev/api/people/?page=2',
  previous: null,
  results: [
    {
      name: 'Luke Skywalker',
      height: '172',
      mass: '77',
      hair_color: 'blond',
      skin_color: 'fair',
      eye_color: 'blue',
      birth_year: '19BBY',
      gender: 'male',
      homeworld: 'https://swapi.dev/api/planets/1/',
      films: [Array],
      species: [],
      vehicles: [Array],
      starships: [Array],
      created: '2014-12-09T13:50:51.644000Z',
      edited: '2014-12-20T21:17:56.891000Z',
      url: 'https://swapi.dev/api/people/1/'
    },
    {
      name: 'C-3PO',
      height: '167',
      mass: '75',
      hair_color: 'n/a',
      skin_color: 'gold',
      eye_color: 'yellow',
      birth_year: '112BBY',
      gender: 'n/a',
      homeworld: 'https://swapi.dev/api/planets/1/',
      films: [Array],
      species: [Array],
      vehicles: [],
      starships: [],
      created: '2014-12-10T15:10:51.357000Z',
      edited: '2014-12-20T21:17:50.309000Z',
      url: 'https://swapi.dev/api/people/2/'
    }
}

So, you have people.results which is an array and you can access people.results[n] to get an item from that array. That item will be an object which has properties like .name, .height, etc...


The specific planet URL you show returns a single planet object like this:

{
  name: 'Alderaan',
  rotation_period: '24',
  orbital_period: '364',
  diameter: '12500',
  climate: 'temperate',
  gravity: '1 standard',
  terrain: 'grasslands, mountains',
  surface_water: '40',
  population: '2000000000',
  residents: [
    'https://swapi.dev/api/people/5/',
    'https://swapi.dev/api/people/68/',
    'https://swapi.dev/api/people/81/'
  ],
  films: [
    'https://swapi.dev/api/films/1/',
    'https://swapi.dev/api/films/6/'
  ],
  created: '2014-12-10T11:35:48.479000Z',
  edited: '2014-12-20T20:58:18.420000Z',
  url: 'https://swapi.dev/api/planets/2/'
}

So, you access properties on that object as in planet.name.


Notice that the people results are paged. There are 82 total results, but only 10 come in this first result. The rest come with results for other pages such as https://swapi.dev/api/people/?page=2.

CodePudding user response:

Similar to this answer but using async/await to avoid callback hell. If you can, try using this approach. Why?

Excellent recommendation in that answer by jfriend00 to use Promise.all instead of separate fetch calls, as that enables fetching to happen in parallel. To know more.

sandbox to test and try

const fetchData = async (...args) => {
  try {
    const response = await fetch(...args);
    return response.json();
  } catch (err) {
    throw new Error(`fetch failed with status ${err?.message}`);
  }
};

const updateDOM = (people, planet) => {
  document.getElementById("people").innerHTML = 
   people.results.reduce((s, p) => s   `<div>${p.name}</div>`, "");
  document.getElementById("planets").innerHTML = `<div>${planet.name}</div>`;
};

const populateData = async () => {
  try {
    const [people, planet] = await Promise.all([
      fetchData("https://swapi.dev/api/people/"),
      fetchData("https://swapi.dev/api/planets/2/"),
    ]);

    // do stuff with 'people' or 'planet'
    // example, get
    // const firstPersonsHomeworld = people.results[0].homeworld;
    // console.log(firstPersonsHomeworld);
    // or
    // const planetName = planet.name;
    // console.log(planetName);

    updateDOM(people, planet);
  } catch (err) {
    // errorHandler(err);
    console.error(err);
  }
};

// start app
populateData();
  • Related