views:

49

answers:

6

Hi there,

I have this code

var stats =  {
    GetMetaData : function() {
        var url = 'http://www.bungie.net/api/reach/reachapijson.svc/game/metadata/'+storage.get('apikey');
        $.ajax({
            url: url,
            success: function(data) {
                return data;
            }
        });
        return 'abc';
    }
}

I call the function using stats.GetMetaData();

I would expect the value returned to be the data variable from the ajax request. But instead it is the string 'abc' why is this?

How can I return the data variable?

I tried doing return $.ajax({ but that just return the function code.

+4  A: 

Because jquery ajax requests are asynchronous by default. You can make request synchronous by using async: false option or (better) use callback function.
Also, as CharlesLeaf notes, using synchronous request will lock up the browser until response is received.

About the whole concept of asynchronous operations.
I would link some explanation from jquery site, but it seems to be down now.

Nikita Rybak
Small addition to your good answer; synchronous requests will lock up your browser until it is finished. Does not help with user experience ;)
CharlesLeaf
In this case nothing is actually allowed to happen until the request completes as the entire extension needs the data (it contains image urls ect). So forcing it to be synchronous it useful.
Hailwood
Also, How would I handle the call back function as this function is to be used all over the place to get the data and it is the response object that is required. (I know someone will say cache it and I am, but there are several functions like this.)
Hailwood
@Hailwood: Forcing synchronous is never (let's say very rarely) useful in browser scripting. If your server takes 2 seconds to respond, the web interface will freeze for 2 seconds. Keep in mind that JavaScript shares the same single thread with the page rendering. A blocking (synchronous) operation, like a long `while` loop freezes the browser.
Daniel Vassallo
@Hailwood - as forcing it to be synchronous is useful, the downside is that **if** the request never complete, the browser will stay lock up.
Reigel
+1  A: 

You will not be able to handle the return value that you are returning from your success callback, for the following reasons:

  • First of all, your return data statement is returning from the success callback, and not from the outer GetMetaData function.

  • But in addition, by the time your success callback is invoked, the GetMetaData function will have already returned. Keep in mind that $.ajax() is asynchronous (non-blocking) by default. Asynchronous is the A in AJAX.

You should handle the response data within the callback directly, or call a helper function to handle the response. Since functions are first class citizens in JavaScript, you could pass this "helper function" as an argument to your GetMetaData function, as @Guffa suggested in the other answer.

Daniel Vassallo
A: 

Since the request is going to be asynchronous, the way to access data is via a callback function, which in this case is the function assigned to success property. You could make the request synchronous, but that's a blocking call which I wouldn't recommend as the browser is locked until the request returns.

Russ Cam
A: 
var stats =  {
    GetMetaData : function() {
        var url = 'http://www.bungie.net/api/reach/reachapijson.svc/game/metadata/'+storage.get('apikey');
        var result;
        $.ajax({
            url: url,
            async: false,
            success: function(data) {
                result = data;
            }
        });

        return result;
    }
}
Jakub Konecki
+1  A: 

The AJAX call is asynchronous, which means that the call returns immediately, and the callback function is called when the data arrives. As your GetMetaData method has already finished, the value that the callback returns is ignored.

You could make the call synchonous, but you should avoid that if possible, as it freezes the browser until the response arrives. The usual way is to use a callback function.

Add a callback to the method:

var stats =  {
  GetMetaData : function(callback) {
    var url = 'http://www.bungie.net/api/reach/reachapijson.svc/game/metadata/'+storage.get('apikey');
    $.ajax({
        url: url,
        success: callback
    });
  }
}

Call it using:

stats.GetMetaData(function(data){
  // do something with the data
});
Guffa
+1 nice workaround. neat.
Reigel
A: 

In your success function call the javascript function you have that will process the data, i.e.:

        success: function(data) {
            DoSomthingWithThe(data);
        }

        ...

    function DoSomethingWithThe(data) {
       // Do something useful
    }

Your problem is that the AJAX call is asynchronous so 'success' isn't called until some time after your GetMetaData function has exited, when the remote server has returned the data. You could elect to go synchronous and wait for the response but it's much better to use a callback function as indicated above.

Lazarus