Zoinks10
Zoinks10

Reputation: 629

Why can I get console.log(variable) to give my value but not return variable?

In my code I'm loading data from json using d3.json - and in order to get it working I call another function once the data is loaded and pass the json across there for processing. This seems to be working, but still refuses to return anything but "undefined".

My code:

function GetDataFromJson() {
      var jsonData;
    d3.json("http://localhost:8000/pipeline.json", function(dataFromServer){
        jsonData = dataFromServer; 
          NewValue(jsonData);
     });
    }

and

function NewValue(data){
  var jsonData = data;
  headers = ["Won"];
  var myTotal = 0;
      chunks = (headers.map(function(priceRange) {
          return jsonData.map(function(d) {
            return {y: +d[priceRange]};
          });
      }));
      var myTarget = 10000000;
      chunks.forEach( function (arrayItem)
          {
            var l = 12;
            for(var i = 0; i < l; i++) {
              myTotal += arrayItem[i].y;
            };
          });
      myTotal = myTotal/myTarget*100;
      return myTotal;
}

I'm running this in Firefox Firebug using GetDataFromJson() and with the code above as-is I just get "undefined" in the console. If I add a line console.log(myTotal) before the return statement I get "undefined" and "37.5" returned as 2 separate lines - 37.5 being the correct value from the data I parsed in.

Why isn't return giving my myTotal as the result of the function whereas console.log() is?

Adding Json data

[
  {
    "Month": "Jan",
    "Prospecting": 0,
    "Qualifying": 0,
    "Demonstrating": 0,
    "Negotiating": 0,
    "Won": 1000000,
    "Lost": 350000
  },
  {
    "Month": "Feb",
    "Prospecting": 0,
    "Qualifying": 0,
    "Demonstrating": 0,
    "Negotiating": 0,
    "Won": 750000,
    "Lost": 2750775
  },
  {
    "Month": "Mar",
    "Prospecting": 0,
    "Qualifying": 0,
    "Demonstrating": 0,
    "Negotiating": 250000,
    "Won": 2000000,
    "Lost": 750000
  },
  {
    "Month": "Apr",
    "Prospecting": 0,
    "Qualifying": 0,
    "Demonstrating": 0,
    "Negotiating": 1375000,
    "Won": 0,
    "Lost": 0
  },
  {
    "Month": "May",
    "Prospecting": 0,
    "Qualifying": 0,
    "Demonstrating": 750000,
    "Negotiating": 0,
    "Won": 0,
    "Lost": 0
  },
  {
    "Month": "Jun",
    "Prospecting": 0,
    "Qualifying": 0,
    "Demonstrating": 325000,
    "Negotiating": 0,
    "Won": 0,
    "Lost": 0
  },
  {
    "Month": "Jul",
    "Prospecting": 0,
    "Qualifying": 50000,
    "Demonstrating": 1000000,
    "Negotiating": 0,
    "Won": 0,
    "Lost": 0
  },
  {
    "Month": "Aug",
    "Prospecting": 10000,
    "Qualifying": 35000,
    "Demonstrating": 0,
    "Negotiating": 0,
    "Won": 0,
    "Lost": 0
  },
  {
    "Month": "Sep",
    "Prospecting": 12250,
    "Qualifying": 22500,
    "Demonstrating": 0,
    "Negotiating": 0,
    "Won": 0,
    "Lost": 0
  },
  {
    "Month": "Oct",
    "Prospecting": 0,
    "Qualifying": 0,
    "Demonstrating": 0,
    "Negotiating": 0,
    "Won": 0,
    "Lost": 0
  },
  {
    "Month": "Nov",
    "Prospecting": 100000,
    "Qualifying": 325000,
    "Demonstrating": 750000,
    "Negotiating": 0,
    "Won": 0,
    "Lost": 0
  },
  {
    "Month": "Dec",
    "Prospecting": 120000,
    "Qualifying": 370500,
    "Demonstrating": 670000,
    "Negotiating": 0,
    "Won": 0,
    "Lost": 0
  }
]

Upvotes: 0

Views: 2823

Answers (2)

Gerardo Furtado
Gerardo Furtado

Reputation: 102194

Your function GetDataFromJson() is returning undefined because this is the expected behaviour in JavaScript: undefined is the “default” returned value if a function does not specify one returned value, and your function GetDataFromJson() doesn't have any return.

Provided that both functions work (i.e., no problem with asynchronous codes), in your GetDataFromJson() function you should change this:

NewValue(jsonData);

for this:

return NewValue(jsonData);

So the function could return the same value that you see using console.log.

Upvotes: 0

κροκς
κροκς

Reputation: 590

d3.json is an asynchronous (non-blocking) function. That means it gets called, but the flow of your program keeps running. Therefore your GetDataFromJson returns before d3.json is actually finished and d3.json completes at a later time, once it has fetched the JSON data through the HTTP request.

Solution with callback functions:

// Pass a "callback" function that will get called once
// the asynchronous task of downloading JSON data is finished.
function GetDataFromJson(callback) {
    var jsonData;
    d3.json("http://localhost:8000/pipeline.json", function(dataFromServer){
        jsonData = dataFromServer; 
        callback(NewValue(jsonData));
    });

    // You don't have this return statement in your code, but it's implied.
    // This line gets called before d3.json is finished.
    // It's the line that gives you the undefined when you do 
    // console.log(GetDataFromJson(...));
    // To test this, try changing it to return "foo",
    // you will get "foo" instead of undefined.
    return;
}

And call it like this:

// The inline callback function we pass will get called
// once the async task is finished. Then we can handle the result.
GetDataFromJson(function(result) {
    console.log(result);
});

Note: You can find ways to make that HTTP request synchronous (blocking) and make it work the way you anticipated, but it's not a good practice.

If you'd like to learn more how the event-loop works, I highly recommend this talk by Philip Roberts at JSConf EU 2014, named "What the heck is the event loop anyway?".

Upvotes: 1

Related Questions