2

I'm using jQuery in a discord Javascript bot and at some point, I'm fetching data from the web to build a string made of the retrieved data.

Here what it looks like:

var jsonFinal = '';
var oembed_url = 'http://backend.deviantart.com/oembed?url=http%3A%2F%2Ffav.me%2Fd2enxz7&format=jsonp&callback=?';
$.getJSON(oembed_url, function(data) {
    jsonFinal = "("+data.author_name+")\n"+data.url;
        console.log(jsonFinal);
    });
        
console.log(jsonFinal):

As you can see, the var jsonFinal which is supposed to contain all the data at the end, is initialized blank.

But what happens in fact is that the jsonFinal DOES contain the desired information at the first console.log (inside the function), but becomes null again at the second console.log (it displays nothing).

That mean either the variable jsonFinal is wiped between the two console.log, or these are two distinct variables with the same names: but I fail to get the info from jsonFinal out the function .getJson.

How can I do?

Martin54
  • 1,349
  • 2
  • 13
  • 34
Rackover
  • 91
  • 1
  • 15

3 Answers3

3

This is because $.getJSON is asynchronous.

The second instance of console.log(jsonFinal): runs before the first.

To get the info "out of the function", you need to either call a function from inside $.getJSON, or do your work inside there.

$.getJSON(oembed_url, function(data) {
  jsonFinal = "("+data.author_name+")\n"+data.url;
    fromInside(jsonFinal);
  });

function fromInside(data) {...}

Or you can use Promises, Generators, Async/Await, etc. depending on what version of Node.js you are using, and if you are/aren't using babel.

You can use node-fetch (for a promise based style).

fetch(oembed_url)
.then(res => res.json())
.then(jsonFinal => {
  console.log(jsonFinal)
})

If you are using Node.js v7, unlock async/await behind the harmony flag.

node --harmony-async-await app.js

Then you can actually make the program "wait for jsonFinal to have a value" -- but only inside of a function.

async function getJSON(oembed_url) {
  let response = await fetch(oembed_url)
  let jsonFinal = await response.json()
}
Raphael Rafatpanah
  • 19,082
  • 25
  • 92
  • 158
  • This looks promising and i'm going to try. But as this is a discord bot using NodeJS and not a browser, synchronous methods that take some time to get done is not a problem at all. Is there a way to make the program "wait for jsonFinal to have a value" ? – Rackover Mar 12 '17 at 11:32
  • Note that "as of jQuery 1.5, [the] jQuery XHR object returned by `$.getJSON()` implements the `Promise` interface, giving it all the properties, methods, and behavior of a `Promise`." – Whymarrh Mar 12 '17 at 11:41
  • 1
    @Rackover, Updated. @Whymarrh, sure. But in case he was only using `jQuery` for it's `$.getJSON()` method (very likely), he may drop his jQuery dependency for something like `node-fetch`. – Raphael Rafatpanah Mar 12 '17 at 11:42
2

As @Raphael mentioned ; You can achieve it by using this :

  $.ajax({
     url: url,
     dataType: 'json',
     async: false,
     data: mydata,
     success: function(data) {
    //stuff
     //...
   }
   });
kourouma_coder
  • 1,078
  • 2
  • 13
  • 24
  • 1
    It is a [**very bad** idea](http://stackoverflow.com/questions/8026191/can-i-use-jquery-getscript-without-a-callback/8026693#8026693) to use synchronous XHR calls. *At some point it will lock up the browser*, causing frustration for the end user. – Useless Code Mar 12 '17 at 14:25
2

$.getJSON is asynchronous method...So outer console.log is getting executed before service returns data.

$.getJSON return promise object. You can use done method of promise to do some action after service call.

$.getJSON( oembed_url, function(data) {
    jsonFinal = "("+data.author_name+")\n"+data.url;
        console.log();
    }).done(function() {
     console.log( jsonFinal );
   });
Amit Gaikwad
  • 923
  • 1
  • 9
  • 15