-1

The alert at the start shows "undefined", why?

The alerts come in this order:

"success!"
"Data" (what it should be)
"undefined"

I read through multiple threads, the problem was always that ajax was asynchronous, so the data was not defined when it was accessed, but in my case the data is there, the alert in my function shows the data BEFORE the other alert where it is undefined!

Very grateful for any help!

I got this code

var data = getData("");
alert(data);            <<<<<<< UNDEFINED

function getData(fileName) {

    $.ajax({
        async:false,
        type: "GET",
        url: "breastCancer.csv",
        dataType: "text",
        success: function (data) {
            var arrData = processData(data);
            alert("success!");
            alert(arrData);      <<<<< WORKS GREAT
            return arrData;
        },
    });

}

function processData(data) {

    var arrData = CSVToArray(data);

    dimensions = arrData[0];
    var objects = [];

    objects[0] = dimensions;

    for (var i = 1; i < arrData.length; i++){
        objects[i] = new Object();

        for (var j = 0; j < dimensions.length; j++){
            objects[i][dimensions[j]] = arrData[i][j];
        }
    }

    return objects;
}

To clarify, I know asynchronous is the way to go for user experience, but this page just has to show data from this call, so its okay for me to wait for it.

Marcel
  • 121
  • 8

4 Answers4

4

Your getData function doesn't return anything.

Bart Louwers
  • 873
  • 9
  • 28
  • it does not? what does the return inside the function do? Okay I see i cannot use my java knowledge for JS. – Marcel Dec 08 '17 at 18:00
  • You return a value from the anonymous "success" function. `getData` itself returns nothing. There's no issue w/ your Java knowledge here, you have two functions, one returns something, one doesn't. – Dave Newton Dec 08 '17 at 18:02
  • 1
    This is technically correct. But this answer should really be a comment. – Eli Richardson Dec 08 '17 at 18:10
  • @Marcel Regarding your Java knowledge: return statements in lambda's also do not return from the function they are contained in. – Bart Louwers Dec 08 '17 at 19:22
1

You need to return it from the function itself.

function getData(fileName) {

    $.ajax({
        async:false,
        type: "GET",
        url: "breastCancer.csv",
        dataType: "text",
        success: function (data) {
            var arrData = processData(data);
            alert("success!");
            alert(arrData);      <<<<< WORKS GREAT
            return arrData;
        },
    });

}

^ This returns the data within getData. But getData doesn't do anything with it: such as returning it.

function getData(fileName) {
    var ourData = "";
    $.ajax({
        async:false,
        type: "GET",
        url: "breastCancer.csv",
        dataType: "text",
        success: function (data) {
            var arrData = processData(data);
            ourData = arrData;
        },
    });
    return ourData;
}

This returns the data from getData to whatever calls that function.

edit: also, don't use async:false. Your browser won't capture any events happening until that AJAX completes. The benefit of asynchronous JS is that...we can! And in this case should.

HB-
  • 635
  • 2
  • 8
  • 21
  • I see, so return inside of ajax does not jump out of the enclosing function. Thanks! – Marcel Dec 08 '17 at 18:02
  • i cannot accept your answer yet because you were so fast! But it works great, thanks again! – Marcel Dec 08 '17 at 18:04
  • @Marcel Of course not--it returns from the function it's in. Java works the same way, e.g., see https://examples.javacodegeeks.com/core-java/java-8-anonymous-function-example/. There's a function defined in a function; returning from the lambda doesn't return from the enclosing function. – Dave Newton Dec 08 '17 at 18:04
  • I see i misunderstood ajax, i didnt see it as a function. Didnt knew you could return from ajax, thanks! – Marcel Dec 08 '17 at 18:07
  • This is just going to return an empty string; this does NOT work. -- You would have to use callbacks or a Promise. – ndugger Dec 08 '17 at 18:44
  • [It works perfectly.](http://hborrino.com/test/) The success function IS a callback. – HB- Dec 08 '17 at 18:59
  • @Rohawk considering that synchronous ajax was deprecated at the browser level, and doesn't even work in FF, I would argue that no, it doesn't. – ndugger Dec 08 '17 at 19:32
  • This was a question about why the variable wasn't defined; this was unaffected by the sync vs. async, even though I agree with not using async false and will edit that into my answer at the risk of being redundant. This most definitely [works in firefox](https://i.imgur.com/ETEnlCT.png), and it certainly doesn't "just return an empty string". It works. – HB- Dec 08 '17 at 22:19
1

Preface: Don't use async: false. But answering the question:

getData doesn't return anything. You're doing a return from the success callback, but that returns something from the success callback, not getData.

To change it so getData returns something, you'd do this:

function getData(fileName) {
    var arrData;
    $.ajax({
        async:false,
        type: "GET",
        url: "breastCancer.csv",
        dataType: "text",
        success: function (data) {
            arrData = processData(data);
        },
    });
    return arrData; // <=== Now `getData` returns something
}

But don't do that. Instead, embrace asynchronous programming and remove async: false. For instance, a callback:

function getData(fileName) {
    $.ajax({
        async:false,
        type: "GET",
        url: "breastCancer.csv",
        dataType: "text",
        success: function (data) {
            callback(processData(data));
        },
    });
}

...called like this:

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

...or a promise ($.ajax returns one, of sorts):

function getData(fileName) {
    return $.ajax({
        async:false,
        type: "GET",
        url: "breastCancer.csv",
        dataType: "text",
        success: function (data) {
            callback(processData(data));
        },
    }).then(data) {
        return processData(data); // <== Becomes the resolution value of `getData`'s promise
    });
}

and then

getData().then(function(data) {
    alert(data);
});
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    as long as this ajax call is done, the page just shows nothing, or placeholder data, it would be more confusing than helpful. But i see the point in async, I will try to comprehend promises, thanks! – Marcel Dec 08 '17 at 18:06
  • @Marcel: Even so, locking up the UI is poor UX, so showing something saying "Loading" (without locking up the UI) that is then replaced by the ajax result is usually best. (I tend to delay the "Loading" by 250ms so that if the call completes quickly, it doesn't flash at the user.) FWIW! Good luck. :-) – T.J. Crowder Dec 08 '17 at 18:23
0

data is undefined because the function getData doesn't return anything. You should have a look at promises.

Andre Kraemer
  • 2,633
  • 1
  • 17
  • 28
  • I did, but i honestly do not understand them at all. I come from a java background, this should be just a "small excersice" but I see I cannot really use my java knowledge in JS.... – Marcel Dec 08 '17 at 18:01
  • 1
    @Marcel I don't see how Java fits in--lambdas work the same way (approximately, at least for the purposes of this discussion). – Dave Newton Dec 08 '17 at 18:06