0

Possible Duplicate:
How to return the response from an AJAX call from a function?

I have a function that reads numerical data from a file online. While the file is retrieved correctly (proven by the value displayed by the alert), when I try to set it to output and then return output, I get an undefined result.

I tried to go through scoping tutorials to no avail. What am I doing wrong?

function readFileFromWeb() {
    var output;

    jQuery.get('http://domain.com', function(data) {
        alert(data);
        output = data;
    });

    return output;
}
Community
  • 1
  • 1
Kang Heong
  • 76
  • 4
  • 5
    Welcome to the wonderful world of **async**! You can't do that. – SLaks Jan 17 '13 at 14:57
  • @FelixKling: I was shocked for a moment when I saw your name under that question... ;/ – georg Jan 17 '13 at 15:00
  • 2 approaches to do what you want here: 1) make you AJAX synchronous 2) implement a timer based functionality that will wait for the response to assign value to a variable you want to use. – marekful Jan 17 '13 at 15:00
  • 3
    @MarcellFülöp Both approaches are awful. I'd recommend understanding and embracing asynchronicity. – bfavaretto Jan 17 '13 at 15:04
  • @bfavarett I don't think I miss anything about understanding async... What approach would you come up with for _returning_ value from ajax callback? – marekful Jan 17 '13 at 15:10
  • 1
    @MarcellFülöp I was not talking about you, I am talking about recommending that to others. If people don't understand async, I recommend they understand it first. The way to go is to not return, and pass/use a callback instead. Or return a promise. – bfavaretto Jan 17 '13 at 15:13
  • @bfavarett You're right in that.. I wasn't arguing how much one understands the concept of async, just recommending a solution for the problem of returning from (A)JAX. I write quite complex JS applications using lots of AJAX and in some (rare) cases, my best choice is making it sync. – marekful Jan 17 '13 at 15:18

2 Answers2

3

Here's how it should be done, via a callback function.

function readFileFromWeb(callback) {
    jQuery.get('http://domain.com', function(data) {
        callback && callback(data);
    });
}

// ...

readFileFromWeb(function (data) {
    alert(data);
});

This is because jQuery.get is an asynchronous function i.e. it doesn't block while executing and thus returns immediately. And that is infact the reason why the jQuery.get function requires a callback function, so that it fires your callback function once the AJAX query has returned.

Thus, you will need to use the same callback pattern when implementing your own readFileFromWeb function.

Andreas Grech
  • 105,982
  • 98
  • 297
  • 360
  • Could you describe what that does `callback && callback(data);`? Callback is executed if it's passed as parameter,isn't it? – kidwon Jan 17 '13 at 15:04
  • 1
    Yup, I'm using the short-circuiting mechanism employed in the logical operators to only invoke `callback` if it contains a truthy value. Note though that this code will still fail if `callback` is not a function because I'm not validating that. – Andreas Grech Jan 17 '13 at 15:08
  • I see, 10x for sharing that – kidwon Jan 17 '13 at 15:10
  • Thanks for the insightful comments, everyone! If I understand correctly: 1. I call readFileFromWeb with a function (to do something with the result) as parameter. 2. readFileFromWeb executes the async get, then calls callback, which is the anonymous function we defined. Is this correct? – Kang Heong Jan 17 '13 at 15:22
  • @KangHeong: Yes. Also keep in mind that the `readFileFromWeb` function returns immediately since `jQuery.get` returns immediately. – Andreas Grech Jan 18 '13 at 09:24
1

It's async, I've commented your code to help you understand the order in which things are happening.

function readFileFromWeb() {
    //1. create variable.
    var output;

    //2. make ajax call.
    jQuery.get('http://domain.com', function(data) {
        alert(data);

        //4. set variable from ajax callback
        output = data;
    });

    //3. return variable.
    return output;
}
Ben Lesh
  • 107,825
  • 47
  • 247
  • 232