Absolute JS newbie here. I am able to use fetch() to get JSON from a URL but I can’t figure out how to do anything with that JSON outside of the fetch itself.

Here’s my code (API key and GPS redacted):

fetch('https://www.airnowapi.org/aq/forecast/latLong/?format=application/json&latitude=X&longitude=X&distance=50&API_KEY=X')
        .then(result => result.json())
        .then((out2) => {     
            console.log('Fetch Output: ', out2);
        }).catch(err => console.error(err)); 

Any code that references out2 other than console.log() call gives an error that out2 is undefined. How do I get access to out2 anywhere else?

  • Max-P
    link
    fedilink
    English
    4
    edit-2
    1 year ago

    Everything that uses out2 must be scoped in that function where the console.log is. That’s because JavaScript is asynchronous: when that entire code block runs, all it does is “queue” the HTTP request to be done, and then continues running your code before the request has even been made. All it knows is that whenever it’s done with the HTTP request, it will call the two functions passed in in the then calls, or if it failed, it’ll run the function passed into the catch call.

    So the code that does whatever with the result must be a separate function to run maybe later when the request completes. Otherwise, this would just freeze the browser or server until it finishes, and it can’t do anything else in the meantime!

    If you want a more procedural style, you can use async functions and await in it. For example:

    try {
        const out = await fetch(...).then(out => out.json())
        // ^ note here that those two `out` variables are completely independent
        console.log('Fetch Output', out)
    } catch (err) {
        console.error(err)
    }
    

    The same can also be written as this:

    try {
        const out = await fetch(...)
        const out2 = out.json()
        console.log('Fetch Output', out)
    } catch (err) {
        console.error(err)
    }
    

    These two examples are just additional syntax sugar to do the same as with the Promise API in your original code. Internally it splits the code into the same sort of nested functions, but it’s easier to read and manage especially if you need to wait on many things.

    Of course you need to be in an async context for that:

    async function doAsyncStuff() {
        // Do the above stuff
    }
    
    doAsyncStuff().catch(err => console.error(err))
    // Here again, the actual execution of `doAsyncStuff` will be put in the queue
    // to be ran later, there's no escaping that. But the
    // code inside the function can make use of the `await` keyword.
    
  • @[email protected]
    link
    fedilink
    English
    3
    edit-2
    1 year ago

    If you leave out the second ‘then()’, the return value of the fetch will be your json (wrapped in a Promise). If you’re calling fetch in an async function, you can do this:

    const out2 = await fetch(url).then(x => x.json()).catch(console.error).

    And then out2 will be the exact same as it was in the second ‘then’, but in the outer scope.

    If making your function asyc is not an option, I’m afraid you have to move your logic to the second ‘then’.

    I recommend looking into javascripts promises. It’s the backbone of asynchronous programming, which is very much what you are trying to do.

    Good luck, and have fun 🙂