Problem with AJAX - loading no data for the 1st time, then working fine [SOLVED]


#1

Hi there,

I’ve encountered an issue. I am about to finish my quote machine, but what bothers me is that I can’t figure out why I’m always getting no data when my app is loaded for the first time. What am I doing wrong? ( I know I’ve used old syntax and mixed it with new syntax, I plan to refactor the entire app once it is working properly)

$(() => {

const url = 'https://random-quote-generator.herokuapp.com/api/quotes/random';
const click = $('#next-quote');
let author = '';
let quote = '';

function genQuote() {
  $.ajax({
      type: 'GET',
      url,
      success: data => {
        author = '- ' + data.author;
        quote = data.quote;
        if (!quote) {
          console.log('generating new data');
          genQuote();
        }
      }
  });
}

(function defaultData() {
  $('#text').html(quote);
  $('#author').html(author);
}());

  click.on('click', () => {
    genQuote();
    console.log('author', author);
    console.log('quote', quote);
    $('#text').html(quote);
    $('#author').html(author);
  });
});

#2

Unless you mean something else, you set author and quote to empty strings, then you run the defaultData function when the whole thing is executed (immediately as this code is loaded, as it’s in an immediately executed function). You’ve written a function to deliberately make what you describe happen (unless you mean something else)


#3

Dan is right.

And for dryness of code, I would put the

  $('#text').html(quote);
  $('#author').html(author);

inside genQuote(), inside the callback or at least a callable function that you can call. Are you ever going to generate a quote without putting it on the screen? And it needs to be in the callback because of async. Then you can call genQuote() once in your program and once in your click handler.


#4

Thanks guys, you’re great, you have saved me! I’ve finally put all the pieces together and here is the result click me! .


#5

Awesome, well done. It’s a great feeling isn’t it, when all this starts making sense?

I only have one concern, this block of code:

        if (!quote) {
          genQuote();
        }
        $('#text').html(quote);
        $('#author').html(author);
      }

So, if there is blank quote, it calls genQuote again. OK, makes sense. But what happens here? We recursively call this and those variables are regenerated in that scope and are written to the HTML, but then when we unravel and come back out to the original genQuote we still have those variables (blank) that are written to the screen, overwriting the good quote. Am I seeing that right? I don’t know, I haven’t had much coffee yet and it was a long night. Perhaps putting them in an else, like this:

        if (!quote) {
          genQuote();
        } else {
          $('#text').html(quote);
          $('#author').html(author);
        } 

My brain is still a little foggy so I’m having a hard time figuring this out right now. I tried experimenting with it but I guess the blank quote is so infrequent that I ran out of time (time for my morning run). Maybe later I’ll set up a timer to keep trying it until it fails just to see what happens. I’m curious.

But still, all in all it looks good.


#6

It does and it’s quite hilarious that the 30-line JS code took me around 2-3 hours to write down, but the worst part was to figure out how to deal with the API as I have never done it before, and before I found an API that was giving me errors with the HTTP request(some security stuff). Anyway, thanks for pointing out that block. I was aware of it, but I forgot to fix that eventually since it had been causing no trouble.

I was experimenting with it as well for a while, then I also added a console.log statement and I figured that the values were set to undefined but right after they were replaced with the right values, so it actually didn’t have a big impact on the app(it was just wasting a bit of memory I suppose.) .


#7

OK, I’ve thought about it a little, and I think the orginal:


ksjazzguitar5h
Awesome, well done. It's a great feeling isn't it, when all this starts making sense?

I only have one concern, this block of code:

        if (!quote) {
          genQuote();
        }
        $('#text').html(quote);
        $('#author').html(author);
      }

would still work, kind of. What would happen is that it would recursively call genQuote and then make it’s ajax call. While that ajax call is running, it will continue on with the code and return control to the calling function. There it would write the blank quote to the html. At some point after that, the ajax call in the recursion call will complete, and will call it’s callback and write the new, complete quote to the screen.

So, you have a race condition, but one that you should always win because the ajax call will always take longer than returning to the calling function.

I think adding the else would take care of that.

It was interesting to try to think that out. Maybe one of these days I’ll test it.


#8

Yeah, but think about how much you learned. It keeps getting easier and easier. Not always at the speed that we hope, but it does. Keep up the good work.