Search code examples
javascriptobjectpromisefetchundefined

Javascript object becomes undefined when appended to another object


I'm trying to fetch some json data, make it into a Javascript object, then assign it to be a child ENFP of the object personalityData. In the code below, I use the function getData to fetch the json, then assign it to personalityData.ENFP. When I log response from the second-to-last-line, response has type object and the values expected. But when I log personalityData.ENFP, it has type undefined and undefined value. I can't figure why this change is happening, since response is immediately assigned to personalityData.ENFP. Also, typeof(personalityData) always returns object.

var personalityData = {}
var getData = async function () {
            const res = await fetch("url")
            if (res.status == 500) {
                return '500 Error';
            } else if (!res.ok) {
                return 'response is not ok';
            }
            const jsonData = await res.json();
            return jsonData;
    }
getData().then(response => personalityData.ENFP = response); 
     //console.log(typeof(response)) returns object
     //console.log(typeof(personalityData.ENFP)) returns undefined
    //console.log(typeof(personalityData)) returns object

Solution

  • You are calling getData, which is async, and trying to console.log the data it is loading immediately in the line below, without waiting for the response.

    Step by step, this is what's happening in your code:

    1. getData is called.
    2. fetch makes a GET request (but the response might take a while to arrive).
    3. All 3 console logs are executed (no response has been received yet).
    4. Eventually, a response for the GET request from above is received.
    5. The code after the await runs.
    6. The .then() callback is executed and the response data is assigned to personalityData.ENFP, but the console.log()s won't run again.

    Try moving the console.logs inside the .then() callback:

    const personalityData = {}
    
    function fakeFetch() {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve({
            status: 200,
            ok: true,
            json: () => ({ foo: 'bar' }),
          });
        }, 2000);
      });
    }
    
    async function getData() {
      const res = await fakeFetch("url");
     
      if (res.status == 500) return '500 Error';
      if (!res.ok) return 'response is not ok';
      
      const jsonData = await res.json();
      
      return jsonData;
    }
    
    getData().then((response) => {
      personalityData.ENFP = response;
      
      console.log(personalityData.ENFP);
    }); 

    Alternatively, you can replace this last .then() with async-await too:

    const personalityData = {}
    
    function fakeFetch() {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve({
            status: 200,
            ok: true,
            json: () => ({ foo: 'bar' }),
          });
        }, 2000);
      });
    }
    
    async function getData() {
      const res = await fakeFetch("url");
     
      if (res.status == 500) return '500 Error';
      if (!res.ok) return 'response is not ok';
      
      const jsonData = await res.json();
      
      return jsonData;
    }
    
    async function loadPersonalityData() {
      const data = await getData();
      
      personalityData.ENFP = data;
      
      console.log(personalityData.ENFP);
    }
    
    loadPersonalityData();