views:

63

answers:

6

I'm sure this is simple, but I'm tripping up over a scope issue in Javascript. I'm doing the following:

$.get(url, function (data){console.log(data);});

This part works fine - I see the string that I want appear in the console. But what I actually want is to take that data variable and place it in a string. Something like this (doesn't work):

string = $.get(url, function (data){return data;});

This gives string a value of [object XMLHttpRequest].

What am I missing?

Oops

Yes, I'm missing the fact that Ajax is, as the name says, asynchronous. Thanks for giving me the slap on the forehead I needed, everyone.

Afterword

The reason I wasn't simply working with the results inside the callback function itself is that I actually need to do multiple AJAX requests every few seconds, gather up the data, and append them all to the page when they're all done.

I've now got that working with a little closure function - the requests are done in a loop, and the data is passed to the closure. When the timer goes off, I call the closure function with no arguments, which tells it "append your previous batch of data to the page (the requests are surely complete by now), clear your cache, and prepare to start receiving new data from the AJAX callbacks in my loop."

Which (hopefully) shows that I'm not an idiot after all. :)

+3  A: 

.get() sends an AJAX GET HTTP request and returns immediately meaning that you cannot assign the result to a variable simply because the result is only available in the success callback (the anonymous function you are passing as second argument). In this callback you could call another functions and pass the data as variable. That's just how AJAX works. The A stands for asynchronous.

Darin Dimitrov
A: 

that data var being passed to your anonymous function is the ajax object itself. If you want to return the response text from the server, you would do something like this:

$.get(url, 
    // data to send
    {
      'foo' : 'bar'
    },
    // receive response
    function(response){
      return response;
    } // response callback function
); // .get()
Crayon Violent
Returning from the success callback of an AJAX request doesn't make much sense.
Darin Dimitrov
A: 

you could do one of two things:

1 - change your GET to be synchronous with {async: false }, you may need to use the $.ajax method to do that. then assign the variable inside the success callback.

2 - put whatever you have that is using the variable inside the success callback.

$.get(url, function (data){
    var string = data;
    useMyString(string);
});
dave thieben
+1  A: 

Ajax requests are done asynchronously1, the last argument of the JQuery's ajax functions is a callback. To answer why your second example doesn't work, you need to understand async callbacks. Alternately, this is similar to the observer pattern where the observable is the Ajax request and the observer is the callback. The steps to perform a request are (roughly) :

  1. create an XmlHttpRequest object
  2. build the request and send it
  3. wait for response
  4. receive a response (there are different states there)
  5. processing the response
  6. Notifying the callback

The argument data in the callback arrives at step 6, while the $.get() call returns at step 2. So your data is not available. You need to set the data at step 6 in some variable and process it from there.


1 requests can be done synchronously, however the A in Ajax stands for Asynchronous. One could use $.get() to perform a synchronized request, but could not be technically called "Ajax". My point of view.

Yanick Rochon
+2  A: 

Returning data from the callback function only returns it to the caller of that callback function, which is jQuery, which does nothing with it.

What you can't do is pass that value from the callback function into the assignment in the surrounding function, and the reason you can't do that is because it would be time travel. The get() method returns instantly, starting off an HTTP request in the background that will complete later. When it does, the callback function is called, but by that time the string has long ago been assigned.

You can't call asynchronous code synchronously, or vice versa. If you want to do something with the result of the HTTP request, you can only do that in a callback function. If you want to provide a function that makes an HTTP request and passes the result back, you have to do it by accepting and calling a callback function yourself:

function getThing(callback) {
    ...
    $.get(url, function(data) {
        callback(data);
    });
}

The alternative is to do the whole lot synchronously, using async: false. But that's bad news for everyone, as the web browser hangs up until the request is complete.

bobince
A: 

This is what you're trying:

var data = $.get(url, function(data){return data;});
// trying to do the stuff you want to do with data

This is what you need to do:

$.get(url, function(data){
    // do the stuff you want to do with data
});
Neall