1

I have the following method in JavaScript:

function getData(){
    var result;

    $.getJSON("app/data/ptl", function (data) {
        if (data == null) {
            return false;
        }

        var x_data = new Array();
        var y_data = new Array();

        $.each(data, function(index, value) {
            x_data.push(index);
            y_data.push(value);
        });

        result = [months_data,value_data];

    });

    alert('');
    return result;
}

When this method is called, the exact data is retrieved. However when I remove alert('') the data is not received. Does anyone know a reasonable explanation for such problem?

Marc B
  • 356,200
  • 43
  • 426
  • 500
Anto
  • 4,265
  • 14
  • 63
  • 113
  • I think you need to show us something else. Here's a simple version of what you're doing that doesn't work with or without the alert for me: http://jsfiddle.net/3yhqf/4/ The answers about asynchronous results are true and should fix your issue, but adding the alert won't let the return statement catch the update. – Ben McCormick Mar 06 '13 at 16:37

3 Answers3

6

That's because your function is asynchronous, and removing the alert makes the return r line being executed before the distant server answers.

You can't simply synchronously return from a function calling an asynchronous work. The usual solution is to provide a callback and execute what you want to do in the callback :

function fetchData(doWithData){
  $.getJSON("app/data/ptl", function (data) {
    if (data == null) {
        return;
    }
    var x_data = new Array();
    var y_data = new Array();
    $.each(data, function(index, value) {
        x_data.push(index);
        y_data.push(value);
    });
    r = [months_data,value_data];
    doWithData(r);
   });
}


fetchData(function(result) {
   // use result here
});
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • shouldn't the original function run to completion regardless of the alert? I'm not sure why the alert delays the return. Doesn't seem to here: http://jsfiddle.net/3yhqf/ – Ben McCormick Mar 06 '13 at 15:39
  • An alert is handled synchronously, it stops the code. – Denys Séguret Mar 06 '13 at 15:41
  • 1
    Mmhmm, but why does the callback run before the getData function finishes? Shouldn't getData run to completion before the callback runs? – Ben McCormick Mar 06 '13 at 15:49
  • @ben336 +1 Your comment is pertinent. I can't give you now a good answer. In fact I can't make OP's code run in my browsers (I don't have IE) even with the alert. – Denys Séguret Mar 06 '13 at 16:02
4

Your alert() and the return r; are OUTSIDE of the 'success' handler of your ajax call. Remember the AJAX calls are asynchronous. The alert forces the browser to wait for you to acknowledge the alert, which allows (usually) the AJAX call to complete and populate your r vairable. Without the alert, the .getJSON() returns immediately, BEFORE r is populated.

Marc B
  • 356,200
  • 43
  • 426
  • 500
  • shouldn't the original function run to completion regardless of the alert? I'm not sure why the alert delays the return. Doesn't seem to here: jsfiddle.net/3yhqf – Ben McCormick Mar 06 '13 at 15:40
  • no. the indenting is off. right BEFORE the alert() line is the `});` which closes the success handler. if the `});` was AFTER the return call, then the code would kinda be more correct. – Marc B Mar 06 '13 at 15:42
  • As far as I can tell, he makes the async request, calls the alert, and then returns. Shouldn't the original function run to completion, then have the callback run? That's how it works in the simpler example in the fiddle. – Ben McCormick Mar 06 '13 at 16:04
  • @ben336: I fixed the indentation in the OP's original. notice that the alert/return are **NOT** part of the .getjson() call. – Marc B Mar 06 '13 at 16:09
  • I'm aware of that. Thats the point. the callback for the JSON call shouldn't run until AFTER the alert and return have completed. JS functions don't run simultaneously (without web workers), one function runs to completion and then the next one runs. The behavior he's describing doesn't make sense – Ben McCormick Mar 06 '13 at 16:13
  • it makes perfect sense. ajax DOES run in the background of the browser, and CAN essentially act as a thread. the .getJSON() call itself will return IMMEDIATELY and proceed to the alert() call. When the actual ajax data comes back, the `function(data() {...}` bit will fire up, INDEPENDENTLY of the main getData() function. That's why the alert makes it "work". it pauses getData(), allowing time for the ajax call to return and populate `r`. What you're saying would be true ONLY if the ajax call was forced into synchronous mode, which'd block the whole browser. – Marc B Mar 06 '13 at 16:26
  • thats not how it works though. See this updated fiddle. The ajax request itself happens in the background, but the callback won't execute till the original function is done executing. See the updated fiddle here: http://jsfiddle.net/3yhqf/4/ I think something else is going on here that isn't seen – Ben McCormick Mar 06 '13 at 16:34
1

The $.getJSON() call sets up an asynchronous process. The function itself returns immediately (almost), but the callback function you pass in will be executed later, when the browser has actually received a response from the server you're contacting. Thus, it inherently makes no sense to return a value from such a callback, as nothing can or will pay attention to it.

Instead, you should do any work that requires access to the retrieved information inside the callback function.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • shouldn't the original function run to completion regardless of the alert? I'm not sure why the alert delays the return. Doesn't seem to here: jsfiddle.net/3yhqf – Ben McCormick Mar 06 '13 at 16:04