0

I'm using Jquery's $.getJSON to get remote JSON from a server. The data is returned and stored in a global variable. The reason this variable is global is because I want that variable and it's data inside, to be the value of another variable outside of that function. So far, the variable with the global variable containing the JSON data, as it's value, has been "undefined" due to the rest of the code not waiting on the JSON. So I think a deferred object will help with this issue however I'm new to this idea. Here is my code below. How can I use a deferred object to allow my code to wait for the JSON data then define my variable outside of the function with the global variable containing the JSON data.

function getStuff(num, onContents){
$.getJSON('http://whateverorigin.org/get?url=' + encodeURIComponent('http://catholic.com/api-radio/' + num) + '&callback=?', function(data){
   //call the oncontents callback instead of returning
   onContents(data.contents);
});
}

//when calling getstuff, pass a function that tells what to do with the contents
getStuff(6387, function(contents){
window.GlobalVar = contents;
});

var NewVar = window.GlobalVar;
alert(NewVar);
Brandon
  • 311
  • 2
  • 16
  • Are you sure you need the global variable? Can you not do whatever it is you need to do with contents inside your callback? – 76484 Mar 22 '14 at 05:46
  • @76484 yes I need a global variable. I can not do what I need to do with the contents inside of my callback. – Brandon Mar 22 '14 at 05:47
  • Well you can't assign GlobalVar to NewVar before you've defined GlobalVar, so you have to move the assignment to inside your callback: NewVar = GlobalVar; The alert will need to be moved to within the callback as well (after the assignment) or removed altogether. – 76484 Mar 22 '14 at 05:51
  • I should add that, from the looks of it, GlobalVar and NewVar are redundant. – 76484 Mar 22 '14 at 05:57
  • The problem is, I'm dealing with JSON data. So the variable ends up undefined. That's why I was resorting to a deferred object. – Brandon Mar 22 '14 at 05:58
  • It's not because you're dealing with JSON data, it's because GlobalVar is undefined. This would fail equally: var NewVar = GlobalVar; GlobalVar = 2; – 76484 Mar 22 '14 at 06:01
  • Globalvar was defined inside the function right? window.GlobalVar = contents; Can you show me a code example of how you would fix it? I'm not quite sure what you mean. – Brandon Mar 22 '14 at 06:05
  • I don't know how to fix it because I don't know what you want to do with contents a.k.a. GlobalVar a.k.a. NewVar. If all you want to do is alert it, then put alert(contents); into the callback. – 76484 Mar 22 '14 at 06:10
  • Maybe there's confusion because I forgot to add a window. to Globalvar outside of the function? What I want to do is, have this window.GlobalVar = contents; which is contained inside of the function, be the value for the NewVar variable outside of the function. This way, NewVar contains the contents of the JSON data which was given to window.GlobalVar inside the function. – Brandon Mar 22 '14 at 06:14
  • What purpose does NewVar serve? A global variable is global, it doesn't need a local representative. – 76484 Mar 22 '14 at 06:17
  • You're right, however NewVar represents what will be $scope.shows in my angular JS project if you're familiar with scope variables. Basically if I had a $scope.shows = "This is a string"; and then in my html had {{shows}} the "This is a string" will be shown. So instead, I want $scope.shows to have window.GlobalVar and it's JSON content as it's value yet I keep getting "undefined" when doing that. NewVar represents the $scope.shows in my code. – Brandon Mar 22 '14 at 06:21
  • The global var isn't going to help you. You need to retrieve your ajax data before your Angular controller is called. I believe what you're looking for is Angular's 'resolve' concept. Maybe this link will be of help: http://docs.angularjs.org/api/ngRoute/provider/$routeProvider – 76484 Mar 22 '14 at 06:42
  • possible duplicate of [How to return the response from an AJAX call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call) – Bergi Mar 22 '14 at 09:38
  • Try putting a fiddle with your code. May help to resolve it much faster!!! – Muhammed Basil Mar 23 '14 at 04:31

1 Answers1

1

It is obvious when reviewing our back-and-forth that there was a lot of confusion in our correspondence. Allow me to sum up:

First, you wanted to define a global variable with the result of your $.getJSON call. Your code was already doing this.

getStuff(6387, function(contents){
    // the following statement will assign the value of 'contents' to the global variable 'GlobalVar'
    window.GlobalVar = contents;
});

I was focussed on the last two lines of your snippet because they were breaking your code:

var NewVar = window.GlobalVar;
alert(NewVar);

The reason this doesn't work is because window.GlobalVar has not been defined yet. Although the line of code where window.GlobalVar is assigned the value of contents precedes the final two lines in the code, the evaluation of these lines is out of sync because the $.getJSON call is asynchronous (which basically means it has its own timeline). So, window.GlobalVar = contents; has not been executed when var NewVar = window.GlobalVar; is attempted - so the line fails.

Due to the asynchronism, any code that relies on contents has to be executed after the $.getJSON call - which is what you hinted at in your original question when you mentioned "deferreds". This is why I urged you to move your last two lines into your callback. Using a deferred would not have been essentially different from what you were already achieving with your callback - a deferred just allows you to attach multiple callbacks that fire on different events.

We finally established that your issue is specific to Angular JS - that is, how to attach ajax data to your $scope. Whereas using a jQuery deferred would not help you, I think using an Angular deferred will. What you need to do is to replace jQuery's getJSON method with the jsonp method from Angular's http service - this will allow you to attach a 'success' handler which will update your $scope (and your view) when your ajax data arrives:

function getStuff(num) {
    $http.jsonp('http://whateverorigin.org/get?url=' + encodeURIComponent('http://catholic.com/api-radio/' + num) + '&callback=JSON_CALLBACK')
        .success(function (contents) {
            $scope.shows = contents;
        });
};
getStuff(6387);

Our ajax response contains an object with a key of 'contents' and a value which is a string of json data, within which is the 'shows' data we want. I'm going to modify the .success handler so that we can get the 'shows' data by deserializing the json string:

.success(function (response) {
    var result = angular.fromJson(response.contents);
    $scope.shows = result.shows;
});

Next, in our Angular, we want to iterate over each 'show' in 'shows' and we can do this using the ng-repeat directive:

<ul>
    <li ng-repeat="show in shows">{{ show.title }}</li>
</ul>
76484
  • 8,498
  • 3
  • 19
  • 30