2

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 third .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 can help me telling where I did wrong in code and maybe different solutions but not so complicated.

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

2
  • You actually have to fetch the second url. (you have it commented out). return fetch(test), instead of return test, and then .then(response => response.json()).then(json => { console.log(json.name) }) Commented Jun 19, 2022 at 19:17
  • Goooood, i understood, the next thing is that i don't know still how to show it on my page .then(response => response.json()).then(json => { test2 = json.name; showRandomUserData(test2); }) and use it in this function showRandomUserData = (randomUser) => { document.querySelector("#name").innerHTML = randomUser.results[randomNumber].name; document.querySelector("#age").innerHtml = randomUser.test2 } Commented Jun 19, 2022 at 19:28

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

8 Comments

but how can i access the name of the planetes, i am trying for people: people.results[0].name and same for planets and it shows me: TypeError: Cannot read properties of undefined (reading '0')
And for this part : // use the results here (such as add items to your web page) i did this let test = document.querySelector("#name"); and under console.log(planets) test.innerHtml = people.results[0].name and it s not working or at least i don't know how to do it correctly
@GeorgeAnghel114 - I edited my answer to show a working snippet that adds results to the web page. It sounds like you were having trouble access the results that you got. See what I added to the end of my answer to explain that.
javascript .then(response => response.json()).then(json => { console.log(json.name) showRandomUserData(json.name); }) trying to pass json.name to showRandomUserData and change innerHtml javascript showRandomUserData = (randomUser) => { document.querySelector("#name").innerHTML = randomUser.results[randomNumber].name; document.querySelector("#age").innerHTML = randomUser.json.name; } what am i doing wrong here?
I did it and i did like you said, showing on my page by changing innerHTML from .then
|
1

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();

2 Comments

FYI, there's no callback hell at all in my answer. Yes, sometimes async/await makes a big difference, but not really in this case.
I never said there is. Just suggested a different approach to the dev, so they can write code that helps 'avoid' callback hell as they extend their code. It might not make a difference here for sure, but it sure does help any programmer (especially beginners) to follow best practices in asynchronous programming.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.