-3

I have this function called getQuotes(), and a console.log() at the end of it that shows the correct value of currentQuote.

function getQuote() {
      $.ajax({
            headers: {
              "X-Mashape-Key": "xxx",
              Accept: "application/json",
              "Content-Type": "application/x-www-form-urlencoded"
            },
            url: 'https://andruxnet-random-famous-quotes.p.mashape.com/?cat=movies',
            success: function(response) {
                  var r = JSON.parse(response);      
                  currentQuote = r.quote;
                  currentAuthor = r.author; 
                  console.log(currentQuote);             
            }
      });
};

The point is: when I call getFunction() (like code below), then show a console.log of my variable currentQuote, it is not receiving the correct value, it still an empty string as declarated. What am I doing wrong ?

$(document).ready(function() {  
    var currentQuote='';
    var currentAuthor='';             
    getQuote();  
    console.log(currentQuote);        
});
  • 1
    since it is an AJAX-request it is likely that the request takes a little time. so maybe wait a few seconds before trying to `console.log(currentQuote)` – SaschaP Dec 08 '16 at 17:47
  • 2
    Quoting in this case doesn't matter for JS properties, and you'd actually have to write `"Accept":` instead to make it valid. – gyre Dec 08 '16 at 17:48
  • 1
    `$.ajax` is async. You code isn't. That's the story. – Nonemoticoner Dec 08 '16 at 17:48
  • In addition to the above comments on synchronicity, have you debugged to check the response for the values? Also you should do something like Ted Hopp's answer below to ensure the response was received before trying to log the variable. – Philip Rittenhouse Jr. Dec 08 '16 at 18:02

2 Answers2

1

Because getQuote() uses an Ajax call, when you call getQuote(), the operation proceeds asynchronously. That means that when getQuote() returns, the results are not yet available. You can fix this by supplying a call-back function as an argument to getQuote() and calling that function from the success function:

function getQuote(callback) {
    $.ajax({
        headers: {
          "X-Mashape-Key": "xxx",
          "Accept": "application/json",
          "Content-Type": "application/x-www-form-urlencoded"
        },
        url: 'https://andruxnet-random-famous-quotes.p.mashape.com/?cat=movies',
        success: function(response) {
              var r = JSON.parse(response);      
              callback(r.quote, r.author); // Report success to the caller
        }
    });
};

Then:

$(document).ready(function() {  
    getQuote(function(currentQuote, currentAuthor) { 
        console.log(currentQuote);
    });
});

This also eliminates the need for global currentQuote and currentAuthor variables. (Although you could always assign those in the callback, if the values are needed elsewhere.)

Alternatives

You can return a Promise from getQuote and modify the Ajax call to call the promise's resolve method. This is described in the accepted answer in the thread to which this is a duplicate.

Because you are using jQuery, another alternative to passing a call-back function is to return the ajax object itself, which has a convenient done(result) property:

function getQuote() {
    return $ajax({
        headers: {
          "X-Mashape-Key": "xxx",
          "Accept": "application/json",
          "Content-Type": "application/x-www-form-urlencoded"
        },
        url: 'https://andruxnet-random-famous-quotes.p.mashape.com/?cat=movies',
    });
}

And then use:

$(document).ready(function() {
    getQuote().done(function(result) {
        if (result) {
            var r = JSON.parse(response);
            console.log(r.quote);
        }
    });
}};

This is also described in the duplicate thread. See the docs for $ajax() for more information.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
0

You have two separate issues.

First, remove the final console.log from your document-ready callback, and allow the success callback on your AJAX request to do the logging for you.

Second, you have two sets of currentQuote and currentAuthor variables: a set of global ones and a set that is locally-scoped to your document-ready callback. You should explicitly define each variable as a global property, like so, to prevent collisions:

$(document).ready(function() {  
    window.currentQuote = ''
    window.currentAuthor = ''             
    getQuote()        
});

function getQuote(cb) {
    $.ajax({
        headers: {
            "X-Mashape-Key": "xxx",
            Accept: "application/json",
            "Content-Type": "application/x-www-form-urlencoded"
        },
        url: 'https://andruxnet-random-famous-quotes.p.mashape.com/?cat=movies',
        success: function (response) {
              var r = JSON.parse(response)     
              window.currentQuote = r.quote
              window.currentAuthor = r.author 
              console.log(currentQuote)     
        }
    })
}

If you want to do more than just log the quotes and authors, there are a few ways to make your life a little easier: callbacks and Promises.

A callback is a function that is passed as a parameter to another (asynchronous) function and is called with some "return" value (like your quote and author) when the async process has completed. Here, I'm using resolve as the callback function.

$(document).ready(function() {            
    getQuote(function (quote, author) {
        // callback -- do stuff with `quote` and `author`
        console.log(quote, author)
    })
})

function getQuote(resolve) {
    $.ajax({
        headers: {
            "X-Mashape-Key": "xxx",
            Accept: "application/json",
            "Content-Type": "application/x-www-form-urlencoded"
        },
        url: 'https://andruxnet-random-famous-quotes.p.mashape.com/?cat=movies',
        success: function (response) {
              var result = JSON.parse(response)     
              resolve(r.quote, r.author)   
        }
    })
}

Promises are a more modern way to handle async code, but they are also less widely supported by default (This can be remedied with a polyfill). Promises are outside of the scope of this answer, but if you want more information then I would suggest checking out the Promise page on the Mozilla Development Network.

gyre
  • 16,369
  • 3
  • 37
  • 47