0

Just wanting to populate myObj with data from within the get request. According to my console.log(myObj) everythings seems to be their but can't access. I'm sure their is a simple answer to this. Thanks.

function getInfo() {
  var myObj = {};
  $.get("http://ipinfo.io", function(response) {
    myObj.city = response.city;
    myObj.region = response.region;
  }, "jsonp");
  console.log(myObj.city);  //undefined
  return myObj;
}

var myStuff = getInfo();  //Object {} just as I expected obviously.
console.log(myStuff)  // Object shows all my key value pairs but -->
console.log(myStuff.city);  // undefined  why? 
dragonore
  • 783
  • 2
  • 11
  • 25
  • 4
    Read about "callback/event driven programming" and "async". `response` is only available inside the callback function. The rest of your logic should be called from in there. – Rudie Jan 09 '16 at 23:48
  • 1
    Possible duplicate of [Ajax jquery async return value](http://stackoverflow.com/questions/4555079/ajax-jquery-async-return-value) – Rudie Jan 09 '16 at 23:48
  • welcome to the world of callbacks. Before you know it you'll be levels deep. – Ryan Jan 09 '16 at 23:58
  • Appreciate it folks, the normal JavaScript I do is mainly design only, I finshed reading some of that Rudie. Thumbs up. – dragonore Jan 10 '16 at 00:07

3 Answers3

2

It is more suitable to use promises. You can try something like this:

function getInfo() {
  var dfd = $.Deferred();

  $.get("http://ipinfo.io", function(response) {
    myObj.city = response.city;
    myObj.region = response.region;
    dfd.resolve(myObj);
  }, "jsonp");

  // Return the Promise so caller can't change the Deferred
  return dfd.promise();
}

getInfo().done(function(myStuff) {
  console.log(myStuff);
  console.log(myStuff.city);
});

With promises the code is one idea elegant.

Georgi Naumov
  • 4,160
  • 4
  • 40
  • 62
1

It return undefine because the request didn't response yet then the function returned the value. Your request was asynchronous meaning your function wont wait for your get request. it would return what ever myObj is.

You can try something like

function getInfo(callback){
     $.get(..., function(res){
            var myObj = …;
             callback(myObj);
     }
}

when ever your request is finished, it would call the callback function and pass in the myObj. so you need to pass in a anonymous function that expect 1 argument to pass in the myObj from the response

getInfo(function(data){
    //data should be myObj
});
John Pangilinan
  • 953
  • 1
  • 8
  • 25
1

$.get is an asynchronous operation which means that it returns immediately (without running the code in your callback function first). The callback will only be executed at some point in the future when the GET request is finished. In the meantime the code following the $.get call will be executed.

What you're seeing is a result of a specific execution order in which the GET request happened not to finish before the following code was executed. In other words you have a race condition.

In theory , if the GET request finished almost instantly, it would be possible for the callback to execute before your log statements and therefore not print undefined. This is highly unlikely, however, as the time it takes to execute log instructions are much(!) less than what it takes to execute the GET request.

To fix the issue you need to ensure that you're log statements are always run only after the GET request is finished. The idiomatic way to do this in JS is with callbacks - e.g. pass a function which contains the code to execute and call it from inside the response handler:

function getInfo(callback) {
  var myObj = {};
  $.get("http://ipinfo.io", function(response) {
    myObj.city = response.city;
    myObj.region = response.region;
    callback(myObj);
  }, "jsonp");
  console.log(myObj.city);  //undefined
}

getInfo(function(myStuff) {
    console.log(myStuff)
    console.log(myStuff.city);
});
olerass
  • 410
  • 2
  • 4
  • 8