Zoinks10 Zoinks10 - 4 months ago 7
Javascript Question

Can I get a value returned from a $.Deferred() that can be used in the display?

I am using the

$.Deferred
method to try and get a function to load some Json, work on the results, then pass the value back to another function that will use the result (in this case I expect an integer). For some reason I can get this integer displayed using either
alert
or
console.log
functions, but when it comes to using it as the return value of the actual function the code falls over and returns
undefined
.

For reference here's my code:

function NewValue(){
var dataPromise = GetDataFromJson();
dataPromise.done(function(data){
//note both console.log(data) and alert(data) deliver the correct result here
return data;
});
}

function GetDataFromJson() {
var jsonData;
var deferred = $.Deferred();
d3.json("http://localhost:8000/pipeline.json", function(dataFromServer){
jsonData = dataFromServer;
headers = ["Won"];
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;
deferred.resolve(myTotal);
});
return deferred.promise();
}


Is it ever possible to return the value from
GetDataFromJson()
and use it, or will I only ever be able to log it to the console?

EDIT after reading through the answer the only way to do this is to call the gauge update function within my GetDataFromJson call - all these promises were seemingly pointless distractions from just passing the right info across:

function GetDataFromJson(f) {
var jsonData;
var deferred = $.Deferred();
d3.json("http://localhost:8000/pipeline.json", function(dataFromServer){
jsonData = dataFromServer;
if( f == "Current"){
console.log('c');
headers = ["Won"]
} else if( f == "Projected"){
console.log('p');
headers = ["Won", "Prospecting", "Qualifying", "Demonstrating", "Negotiating"]
}
else {
alert('An error has occured')
};

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;
gauge5.update(myTotal);
deferred.resolve(myTotal);
});
return true;
}


Now I call GetDataFromJson() directly from a click on a radio button, and pass either "Current" or "Projected" inside that call so the right data is shown. Feels stupid that I've wasted a week studying this, but hopefully this answer will help others. You can't extract data from these promises but you can call another function (in my case gauge5.update) and send it the value you want to use.

Answer

You are returning 'data' inside callback, not in function NewValue. NewValue should return promise and caller of NewValue should assign a callback on completion of this promise.

function NewValue(){
  var defer = $.Deferred();
  var dataPromise = GetDataFromJson();
  dataPromise.done(function(data){
  //note both console.log(data) and alert(data) deliver the correct result here
    deferred.resolve(data);
  });
  return deferred.promise();
}

 NewValue()
  .done(function(data){
      // do whatever
   })

I am assuming you want to process the data further in NewValue function, else why can't you directly call GetDataFromJson?

Comments