3

First off I am new to javascript and this is my first 'project' in this language, so I apologize for my noobiness in advance.

I am using leaflet and D3 in this project and I can't seem to get this function to return anything except for 'Undefined'. At first I though I wasn't returning from the function properly so I tried to duplicate the error on a smaller scale here:

http://jsfiddle.net/KhqwR/

However, that worked for me so now I am a little lost on what to do.

Here is a simple version of my code, I tried to remove everything that didn't seem relevant and changed the names to make it easier to understand:

$(function () {
  ...  
  function getThings(code) {    
    d3.csv("data.csv", function(data){
      for (var i = 0, len = data.length; i < len; i++){        
        if (data[i].code == code){                     
          alert("return 5!")
          return 5;
        }
        else{
          return 0;
        }
      }
    })
  }

  L.geoJson( features,  {
    style: function (feature) {
      return { opacity: 0, fillOpacity: 0.5, fillColor: "#0f0" };
    },
    onEachFeature: function(feature, layer){ 
      var test = getThings(5);      
      alert(test);
      ...

I consistently get to the "return 5!" alert and then at the alert(test) I just get "Undefined".

Does anybody know where I went wrong? Thanks in advance!

Joel
  • 399
  • 1
  • 4
  • 16

3 Answers3

2

d3.csv actually returns a useful value that can be used for attaching relevant callbacks. However, because the getThings doesn't have a return statement, then it will always yield undefined when invoked.

Remember that return applies to the nearest enclosing function, including anonymous functions such as the provided callback.

function getThings(code) {
    /* Without an explicit return, a function always evaluates
       to undefined when invoked. */
    return d3.csv("data.csv", function(data){ .. });
})

var test = getThings(..);
/* Now test is NOT undefined, but is also NOT the data
   for the asynchronous reasons discussed elsewhere.
   See the link above for correct usage. */
test.row(..);
user2864740
  • 60,010
  • 15
  • 145
  • 220
1

d3.csv() is async. Which means, the function getThings() kicks off d3.csv() and instantly returns undefined

From d3 documentation:

Issues an HTTP GET request for the comma-separated values (CSV) file at the specified url. The file contents are assumed to be RFC4180-compliant. The mime type of the request will be "text/csv". The request is processed asynchronously, such that this method returns immediately after opening the request.

Ayush
  • 41,754
  • 51
  • 164
  • 239
  • While true, if the OP was using `return` in getThings function, `test` would be assigned a non-undefined value (but not the data). – user2864740 Feb 07 '14 at 21:50
  • 1
    Right. If he was doing `return d3.csv()`, we would be returned, most probably, a promise. – Ayush Feb 08 '14 at 00:38
0

This is happening due to Javascript Async Nature. Use function Callback.

Manish Kumar
  • 571
  • 3
  • 15