Help for Random Quote Machine Using Fetch API

Hi guys. I’m working on the random quote machine project and I’ve been able to get most of the work done except for one. The “tweet quote” part. I can encode it but the variables I globally set are reset to undefined once the fetch promise has completed running. Can anyone shed some light on this?

document.getElementById('new-quote').addEventListener('click', displayQuotes);
document.body.onload = displayQuotes;

let randomQuote = (input) => Math.floor(Math.random() * input);

var text;
var author;
function displayQuotes() {

    fetch('quotes.json')
        .then((res) => res.json())
        .then((data) => {
            let randomIndex = randomQuote(data.quotes.length);
            text = data.quotes[randomIndex].quote;
            author = data.quotes[randomIndex].author;

            console.log(encodeURIComponent(text));
            let output = `
                <img src="${data.quotes[randomIndex].image}">
                <p id="text">${text}</p>
                <p id="author">- ${author}</p>
            `;
            document.getElementById('quotes').innerHTML = output;
        });
}

document.getElementById('tweet-quote').addEventListener('click', () => {
    location.href='http://www.example.com';
});

Note I’m working with a local JSON file for now.

Just a quick question did you check if values for text and author variables get assigned inside fetch?

Obviously. Where would I bring them from then? They are only initialized as global variables before the displayQuotes. Not assigned. They get assigned in the fetch.

Are you sure that they are getting undefined after the promise have resolved or are you checking them before the fetch promise has resolved, sounds like an async issue to me but can’t be sure, can you do a mock up on codepen ?

1 Like

They log their respective values while in the promise. Outside of it they log undefined.

Will do.

right, sounds like an async issue, try to see if they log when you do this outside

      setTimeout(() => {
        console.log(text, author)
      }, 2000);

If they do, then it is def. an async issue, basically, what the above does is wait a couple secs till the variables are set (i.e. the resolution of the fetch promise) before logging them

Yeah they log. Only once if they’re outside of displayQuotes().

Right, not sure where you are in your JavaScript journey but this problem will most certainly have a repeated occurrence until you start getting used to it. In essence, you can’t do asynchronous things (like fetching data) and write your code synchronously, the synchronous code will be executed before the async due to the call stack and where the event loop is placed in the call stack, if you want more detail you can read about it here (or just google Asynchronous JavaScript)

One way to solve your problem above is to do everything you need with the fetched data inside the then statement

Yeah I was considering that. Somehow have both click events call the same function so that the data displayed and the data passed to the url will both be the same but it sounds tedious and it looks like I should read up on the topic you mentioned first instead of use a shortcut.

Thanks @Dereje1 that was a helpful link