13

How can I console log - or do any thing with the data returned from inside an async function?

example: JS FILE:

   async function getData(){
      try {
         $.getJSON('./data.json', (data) => {
            return data;
         });
      } catch(error) {
         console.log("error" + error);
      } finally {
         console.log('done');
      }
   }

   console.log(getData());

JSON FILE:

{
   "stuff": {
      "First": {
         "FirstA": {
            "year": [2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017],
            "Categories": ["Suspension", "Electrical", "Performance", "Motor"]
         },
         "FirstB": {
            "year": [2007, 2008, 2009, 2010, 2011, 2012],
            "Categories": ["Suspension", "Electrical", "Performance", "Motor"]
         }
      },
      "Second": {
         "SecondA": {
            "year": [2002, 2003, 2004, 2005, 2006],
            "Categories": ["Suspension", "Electrical", "Performance", "Motor"]
         },
         "SecondB": {
            "year": [2007, 2008, 2009, 2010, 2011, 2012],
            "Categories": ["Suspension", "Electrical", "Performance", "Motor"]
         }
      }
   }
}

How can I return / get access to all the information in the JSON file and work with it. for example I'd like to take the "First" and "Second" and add them to a div. Same with "FirstA" and "FirstB" and "SecondA" and "SecondB"...and so on.

Right now as it stands, I get Promise {: undefined}

Any help would be greatly appreciated.

---------UPDATE---------

If I run the console log inside the function I then can see the json data, but I need access to the data outside the function.

Serge

Sergio
  • 792
  • 3
  • 10
  • 35
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Andreas Dec 30 '17 at 17:07

2 Answers2

22

Two issues:

  1. To set the resolution value of the promise created by the async function, you have to use a return statement from the async function itself. Your code has a return in the getJSON callback (which is ignored), not the async function itself.

  2. To get the resolution value of an async function, you must await it (or consume its promise in the older way, via then, etc.).

For #1, you could return the result of awaiting getJSON:

async function getData() {
    try {
        return await $.getJSON('./data.json').promise();
    }
    catch (error) {
        console.log("error" + error);
    }
    finally {
        console.log('done');
    }
}

And for #2, you'd need to either await your function (this would, in turn, need to be inside an asyncfunction):

console.log(await getData());

...or consume its promise via then:

getData().then(data => {
    console.log(data);
});

Side note: Your getData hides errors, turning them into resolutions with the value undefined, which is generally not a good idea. Instead, ensure that it propagates the error:

catch (error) {
    console.log("error" + error);
    throw error;
}

Then, naturally, ensure that anything using getData either handles or propagates the error, making sure something somewhere does handle it (otherwise, you get an "unhandled rejection" error).


Re your comment

how would I access the "stuff" in the json file from the log outside the function?

The async result / resolution value of getData is the object the JSON defined (it's no longer JSON, it's been parsed). So you'd use .stuff on it, e.g.:

// In an `async` function
console.log((await getData()).stuff);

// Or using `then`:
getData().then(data => {
    console.log(data.stuff);
});
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • T.J. Crowder in the first example what is the "i" in the i.getJSON and where is it coming from? I know I am sprinkling some jQuery in there with the getJSON method, but just testing to see if this would work. – Sergio Dec 30 '17 at 17:11
  • @Sergio: It was a typo (now fixed). Which is odd, given that I used copy and paste. So maybe not a typo, but rather an editing error. :-) – T.J. Crowder Dec 30 '17 at 17:12
  • hahaha...it's no biggie. Ok, just tested and now something is happening. – Sergio Dec 30 '17 at 17:14
  • now how would I access the "stuff" in the json file from the log outside the function? I tried console.log(getData().stuff); and I get undefined. – Sergio Dec 30 '17 at 17:16
  • @Sergio: Yes, of course you do, because `getData` returns a promise, and promises don't have a property called `stuff`. I've added to the end of the answer. – T.J. Crowder Dec 30 '17 at 17:20
  • Perfect. Thank you for your help. Using the .then method worked for me. the await kept giving me an error of Unexpected identifier – Sergio Dec 30 '17 at 17:27
  • @Sergio: No worries. Yes. As I said above, you can only use `await` in an `async` function. – T.J. Crowder Dec 30 '17 at 17:30
  • 1
    aahh... so the "await" can only be used inside the async function. Outside the async function "then" should be used - as you clearly commented out in your example lol. – Sergio Dec 30 '17 at 17:33
  • T.J. I have a follow-up question posted here...if you can, can you take a look at it. Thanks. https://stackoverflow.com/questions/48036910/javascript-async-function-inside-jquery-on-change-function-returns-undefined – Sergio Dec 30 '17 at 18:52
  • with arrow function you could just do `async () => console.log(await getData())` – buncis Feb 09 '19 at 08:44
0

I use following way. Create a async function like following:

private consoleLogAsync = async (message: string, other?: any) => {
    await new Promise((resolve) => setTimeout(resolve, 0)).then(() => console.info(message, other));
};

Use it in your async function where you want to log e.g.:

 await this.consoleLogAsync('myMessage', myObject);
Adam Ri
  • 347
  • 2
  • 15