JavaScript Asynchronous Programming with JavaScript Asynchronous JavaScript with Callbacks Implement a Callback

Zaid Khan
Zaid Khan
12,740 Points

Same code and still getting an error

Hi, I am getting this error in the console:

Uncaught TypeError: Cannot read property 'source' of undefined at generateHTML

I don't understand why it can't read data.thumbnail.source

Here is my code:

// Generate the markup for each profile
function generateHTML(data) {
  const section = document.createElement('section');
  peopleList.appendChild(section);
  section.innerHTML = `
    <img src=${data.thumbnail.source}>
    <h2>${data.title}</h2>
    <p>${data.description}</p>
    <p>${data.extract}</p>
  `;
}

btn.addEventListener('click', (event) =>{
    getJSON(astrosUrl, (json) => {
        json.people.map( person => {
            getJSON(wikiUrl + person.name, generateHTML);
        });
    });
    event.target.remove();
});

Someone has also asked the same question but its answer didn't work. Would really appreciate any help.

6 Answers

Cameron Childres
MOD
Cameron Childres
Treehouse Moderator 11,545 Points

Hey Zaid,

The code as written in this lesson assumes that astronauts' names will return their specific page. It doesn't account for Wikipedia having multiple people of the same name (leading to disambiguation pages) or alternate spellings of names (leading to redirect pages). Both of these situations return data that does not have an associated thumbnail. If there's no thumbnail property then trying to access the source property of thumbnail will give an error. You can see this for yourself by adding a console.log(data) statement to generateHTML() and viewing the properties of the objects produced.

Here's a decent workaround -- replace the section.innerHTML statement with this:

    if (person.thumbnail) { 
      section.innerHTML = `<img src=${person.thumbnail.source}>` ; 
    } 
    section.innerHTML +=  `
      <span>${person.craft}</span>
      <h2>${person.title}</h2>
      <p>${person.description}</p>
      <p>${person.extract}</p>
    `;

This way the code only looks for the image source if the thumbnail property is defined. There's plenty of other ways the code can be cleaned up (disambiguation pages and redirects will produce weird entries) but this will work well enough for the goals of the lesson.

Could you try out this workaround and see if it works for you? Let me know if you have any questions.

Zaid Khan
Zaid Khan
12,740 Points

Hi Cameron,

Thank you for replying.

This was very helpful.

I went again to my code and added

const img_src = (data.thumbnail && data.thumbnail.source) ? data.thumbnail.source : "";
section.innerHTML = `<img src=${img_src}>`

with double quotes this time and it worked, Although I can only view 4 out of 7 astronauts images because of disambiguation.

Cameron Childres
Cameron Childres
Treehouse Moderator 11,545 Points

Great to hear! I think that's the best solution for the purposes of this course. I'm curious about a way to correct for disambiguation pages and redirects but that's a bit outside of the scope for the lesson.

Mike Straw
Mike Straw
6,474 Points

I did it this way, so that at least the name is displayed.

// Generate the markup for each profile
function generateHTML(data) {
  const section = document.createElement('section');
  peopleList.appendChild(section);
  if ( data.type === 'standard' ) {
    section.innerHTML = `
      <img src=${data.thumbnail.source}>
      <h2>${data.title}</h2>
      <p>${data.description}</p>
      <p>${data.extract}</p>
    `;
  } else {
    section.innerHTML = `
      <h2>${data.title}</h2>
    `;
  }
}
Zaid Khan
Zaid Khan
12,740 Points

Yeah, For sure I am going to dig deeper into this hitch too.

Nick Huemmer
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Nick Huemmer
Front End Web Development Techdegree Graduate 17,815 Points

I ran into the same issue - I had empty sections without any images or text. I pasted in the code that Zaid linked to and got all the Wiki info for each astronaut, but no thumbnail for three of them (Sergey Ryzhikov, Victor Glover or Michael Hopkins). I also received disambiguation messages for each of the astronauts without thumbnails.

Zaid Khan
Zaid Khan
12,740 Points

Yeah, Nick, I think everyone is going to run into this issue until this gets fixed somehow and, I guess these kinds of issues could be expected when working with APIs.

Nicolle Romero
Nicolle Romero
1,785 Points

I made the following change to just bypass generating HTML for data with type 'disambiguation':

// Generate the markup for each profile
function generateHTML(data) {
  if(data.type === 'disambiguation') {
    return
  }
  const section = document.createElement('section');
  peopleList.appendChild(section);
  section.innerHTML = `
    <img src=${data.thumbnail.source}>
    <h2>${data.title}</h2>
    <p>${data.description}</p>
    <p>${data.extract}</p>
  `;
}
Zoltán Erkel
Zoltán Erkel
6,328 Points

I could not find a solution yet, but is there perhaps a method with which one could filter the returned data for a specific keyword? Like filtering the search on wikipedia for text that contains the words "cosmonaut" || "astronaut" ?