-1

I have 2 csv's that I'm trying to read in, after which I use the data in those two to do stuff:

function getData() {

  var deferredObject = $.Deferred(); //representation of some asynchronous work 
  d3.csv("./parse_shp.csv", function(data) {
    console.log(data);
    shp_array = data;
  });

  d3.csv("./fao_coutnry_shp.csv", function(data) {
    console.log(data);
    fao_array = data;
  });

  //once both of those are done, resolve the promise 
  deferredObject.resolve();

  return deferredObject.promise();
}

function LevenshteinDistance() {
  console.log("do stuff with the data");
}

//call LevenDistance after the promise has been resolved 
getData().then(LevensteinDistance());

But that's not working... it'll print the line "do something with the data" before printing the data of the csv's.

What am I doing wrong? I used this link as an example.

I don't understand how connect deferredObject and getData()? Because even if I create the deferred object in the function, won't it just asynchronously do the csv reads anyway and then erroneously call defferedObject.resolve()?

Anyway, I'm new to promises so any help would be greatly appreciated!!

Barmar
  • 741,623
  • 53
  • 500
  • 612
ocean800
  • 3,489
  • 13
  • 41
  • 73
  • you are resolving the promise before either of the .csv methods have completed. – Kevin B Feb 24 '16 at 21:54
  • @KevinB Thanks! So how would I resolve it after they have completed? Do I have to bind a promise to the csv methods themselves? – ocean800 Feb 24 '16 at 21:55
  • 1
    `getData().then(LevensteinDistance());` is a bug, you should not CALL LevensteinDistance and pass its return value to `then`, you should just pass `LevensteinDistance` (the function) without `()` after it – doug65536 Feb 24 '16 at 21:56
  • @PJSCopeland you should verify with the OP before making substantial changes to the code of a question. – jpaugh Feb 24 '16 at 21:59

1 Answers1

2

The argument to .then() must be a function. You're calling the function immediately, because you have () after the function name. It should be:

getData().then(LevenshteinDistance);
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 1
    OP is also *resolving* the deferred immediately instead of after the 2 d3 callbacks are done. – Brandon Feb 24 '16 at 21:56
  • Yeah, I see that, but I'm not familiar enough with d3.js to know how to fix it. Does `d3.csv()` return a promise? – Barmar Feb 24 '16 at 22:01
  • That's one of my problems, thanks! I guess.. my question is then how would I resolve the deferred objects after the 2 d3 callbacks are done? Would I have to have a promise for each of the csv methods? – ocean800 Feb 24 '16 at 22:02
  • 1
    I think that's what's needed, but I'm not sure how to code it. It's possible that `d3.csv()` returns a promise, but I couldn't find that in the API documentation. – Barmar Feb 24 '16 at 22:06
  • 1
    Looks like you can simply [promisify the callback](http://stackoverflow.com/q/22519784/1048572). – Bergi Feb 24 '16 at 22:10
  • Wrapping it in a Promise.resolve would force it to return it's value/error as a resolved/rejected promise or just return the promise if it was one. Promise.resolve(d3.csv()) – Dtipson Feb 24 '16 at 22:10
  • @Dtipson: It would not be "forced" to do anything. It's just as likely that it returns `undefined`, and then you'd have a promise for that value. – Bergi Feb 24 '16 at 22:11
  • Thanks! I'll found [this](http://stackoverflow.com/questions/13425987/how-do-i-ensure-d3-finishes-loading-several-csvs-before-javascript-runs) so i'll try that first, but if not, i'll look at the other link, thanks! – ocean800 Feb 24 '16 at 22:14
  • Bergi, all I meant is that if it returned a value or a thenable, wrapping it in Promise.resolve would make it consistently return a Promise. I didn't mean to imply that it would magically handle functions that don't return anything. It looks like d3.csv currently uses callbacks though: https://github.com/mbostock/d3/wiki/CSV – Dtipson Feb 24 '16 at 22:49