Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Asynchronous Programming with JavaScript Understanding Promises Using Fetch

I keep getting an error on the console

const astrosUrl = 'http://api.open-notify.org/astros.json';
const wikiUrl = 'https://en.wikipedia.org/api/rest_v1/page/summary/';
const peopleList = document.getElementById('people');
const btn = document.querySelector('button');

function getProfiles(json) {
  const profiles = json.people.map( person => {
    const craft = person.craft;
    return fetch(wikiUrl + person.name)
      .then( response => response.json() )
      .then( profile => {
        return { ...profile, craft };
      })
      .catch( err => console.log('Error Fetching Wiki: ', err) )
  });
  return Promise.all(profiles);
}

function generateHTML(data) {

  data.map(person => {

    const section = document.createElement('section');
    peopleList.appendChild(section);
    section.innerHTML +=  `
      <img src=${person.thumbnail.source}
      <span>${person.craft}</span>
      <img src=${person.thumbnail ? person.thumbnail.source : null}>
      <h2>${person.title}</h2>
      <p>${person.description}</p>
      <p>${person.extract}</p>
    `;
  });

}


btn.addEventListener('click', (event) => {
  event.target.textContent = "Loading...";
  fetch(astrosUrl)
    .then( response => response.json() )
    .then(getProfiles)
    .then(generateHTML)
    .catch(err => {
      peopleList.innerHTML = '<h3>Something went wrong!</h3>';
      console.log(err)
    })
    .finally( () => event.target.remove() )

});

3 Answers

Cameron Childres
Cameron Childres
11,817 Points

Hi Junior,

Take a look at the error in your console:

TypeError: Cannot read property 'source' of undefined
    at callbacks.js:26                 // error originates from line 26
    at Array.map (<anonymous>)         // inside a map method
    at generateHTML (callbacks.js:21)  // inside the generateHTML function

This tells us the nature of the error and where to look for it. On line 26 you have:

<img src=${person.thumbnail.source}

This is the same issue that was causing you trouble on a previous section. Not all of the data returned has a thumbnail property. Additionally your img tag is missing its final angle bracket ">" but this will only cause problems in your HTML.

Two lines later you have a separate img tag that checks if person.thumbnail is valid before accessing the source property:

<img src=${person.thumbnail ? person.thumbnail.source : null}>

While it works for preventing the error, passing null as the source will show a broken image on the page. Passing an empty string instead of null won't show a broken image but will still make an empty img element which gives some odd indentation.

You can use the fix from the previous post which avoids this issue by only producing the img tag if person.thumbnail is defined. You can also solve it with a ternary expression like this:

${person.thumbnail ? `<img src = ${person.thumbnail.source}>` : ""}

I hope this is helpful -- let me know if you have any questions!

Thank you Cameron Childres ! I'm still getting the same error about the property 'source' after I made the correction.

const astrosUrl = 'http://api.open-notify.org/astros.json';
const wikiUrl = 'https://en.wikipedia.org/api/rest_v1/page/summary/';
const peopleList = document.getElementById('people');
const btn = document.querySelector('button');

function getProfiles(json) {
  const profiles = json.people.map( person => {
    const craft = person.craft;
    return fetch(wikiUrl + person.name)
      .then( response => response.json() )
      .then( profile => {
        return { ...profile, craft };
      })
      .catch( err => console.log('Error Fetching Wiki: ', err) )
  });
  return Promise.all(profiles);
}

function generateHTML(data) {

  data.map(person => {

    const section = document.createElement('section');
    peopleList.appendChild(section);
    section.innerHTML +=  `
      ${person.thumbnail ? `<img src = ${person.thumbnail.source}>` : ""}
      <img src=${person.thumbnail.source}>
      <span>${person.craft}</span>
      <h2>${person.title}</h2>
      <p>${person.description}</p>
      <p>${person.extract}</p>
    `;
  });

}


btn.addEventListener('click', (event) => {
  event.target.textContent = "Loading...";
  fetch(astrosUrl)
    .then( response => response.json() )
    .then(getProfiles)
    .then(generateHTML)
    .catch(err => {
      peopleList.innerHTML = '<h3>Something went wrong!</h3>';
      console.log(err)
    })
    .finally( () => event.target.remove() )

});
Cameron Childres
Cameron Childres
11,817 Points

That's because you still have another img tag on the next line.

This line of code says "if person.thumbnail is truthy then return this template of an img tag, otherwise add an empty string":

${person.thumbnail ? `<img src = ${person.thumbnail.source}>` : ""}

The line that you have after it is an img tag, it doesn't check anything, it's just there. If there weren't any errors you would end up with two images.

Ok Cameron Childres ! It works now. Thank you again for all your help!

The last astronaut keeps on returning undefined Promises.js:10 GET https://en.wikipedia.org/api/rest_v1/page/summary/Yulia%20Pereslid 404 (anonymous) @ Promises.js:10 getProfile @ Promises.js:8 Promise.then (async) (anonymous) @ Promises.js:44 Promises.js:10 Fetch failed loading: GET "https://en.wikipedia.org/api/rest_v1/page/summary/Yulia%20Pereslid".

This appears to be a common problem in this course, because there is a disagreement in the spelling of Russian names between http://api.open-notify.org/astros.json and https://en.wikipedia.org/. In the Wiki-article about this astronaut, her name is written as yulia_peresild, not yulia_pereslid, so the AJAX request returns with a 404 error (Source not found), because it is looking for the wrong name. Sadly, the only real way of fixing this in the code, is to implement a manual fix;

    if (person.name != "yulia_pereslid"){ 
      return getJSON(wikiUrl + person.name);      
    } else {
      return getJSON(wikiUrl + "yulia_peresild"); 
    }
  • Of course, by now, this name error is no longer relevant, as she isn't on the list anymore, but another set of names with problems of the same nature has most likely taken over.