user2061886 user2061886 - 17 days ago 5
Javascript Question

how to set a var outside of an async function to use in $scope object

For the last two days I've been reading about promises, callbacks, and generators trying to figure out how I can set a value from a async function that I can then use in a $scope object.

I can't get the promise to resolve then to the

var
, it just returns the promise and not the value, which is what its supposed to do from what I understand. This is where I thought maybe a generator would help maybe?

So, how do I set a
var
from an async function so that I can use that
var
in the object
$scope.options_scn_cst


This is specifically for nvd3, as what I'm trying to do, is to loop through the results from the loopback function
Rpt_scn_cost_v
to find the max value, and then set that as the max value in the Y axis in
yDomain: [min, max]
for nvd3.

My code right now looks like this:

function maxYvalue2() {
return Rpt_scn_cost_v.find({filter: { where: {scenario_id: $stateParams.id}}}).$promise.then(function(response){
var maxYvalue = 0;
var currMaxYvalue = 0;
for (var i=0;i<response.length;i++) {
var currMaxYvalue = parseFloat(response[i].cur_cost) + parseFloat(response[i].tgt_cost);
if (currMaxYvalue > maxYvalue) {
maxYvalue = currMaxYvalue;
};
}
return maxYvalue;
console.log("yVal: ", maxYvalue)
});
};

var mxY = 100000 // <======== when I set it to this maxYvalue2(), it resolves in a promise

console.log('var', mxY)




$scope.options_scn_cst = {
chart: {
type: 'lineChart',
height: 450,
margin : {
top: 20,
right: 20,
bottom: 40,
left: 55
},
x: function(d){ return d.x; },
y: function(d){ return d.y; },
useInteractiveGuideline: true,
dispatch: {
stateChange: function(e){ console.log("stateChange"); },
changeState: function(e){ console.log("changeState"); },
tooltipShow: function(e){ console.log("tooltipShow"); },
tooltipHide: function(e){ console.log("tooltipHide"); }
},
xAxis: {
axisLabel: '',
tickFormat: function(d) { return d3.time.format('%b %y')(new Date(d)); }
},
yDomain: [0, mxY], // <============ I then set mxY here in the $scope object
yAxis: {
axisLabel: '$ / month',
tickFormat: function(d){
return d3.format('$,.0f')(d);
},
axisLabelDistance: -10
},
callback: function(chart){}
},
title: {
enable: true,
text: 'Scenario Costs Over Time'
},
subtitle: {
enable: false,
text: 'Put your Subtitle here.',
css: {
'text-align': 'center',
'margin': '10px 13px 0px 7px'
}
},
caption: {
enable: false,
html: 'Put your Caption Here.',
css: {
'text-align': 'justify',
'margin': '10px 13px 0px 7px'
}
}
};


and then I call the $scope object like this then:

<nvd3 data="data_scn_cst" options="options_scn_cst"></nvd3>


I tried this way as well using $q, but it returns the promise and not the value too...

function maxYvalue2() {

var deferred = $q.defer();

Rpt_scn_cost_v.find({filter: { where: {scenario_id: $stateParams.id}}}).$promise.then(function(response){
var maxYvalue = 0;
var currMaxYvalue = 0;
for (var i=0;i<response.length;i++) {
var currMaxYvalue = parseFloat(response[i].cur_cost) + parseFloat(response[i].tgt_cost);
if (currMaxYvalue > maxYvalue) {
maxYvalue = currMaxYvalue;
};
}
deferred.resolve(maxYvalue)
console.log("yVal: ", maxYvalue)
});

return deferred.promise
};

var mxY = maxYvalue2() // <======== when I set it to this maxYvalue2(), it resolves in a promise

console.log('var', mxY)

Answer

Because your code is by nature asynchronous, you will never get it into your var synchronously, whichever methods you try.

You have a few ways to work around that. One option is to wait until the promise resolves (using its then method) and then, and only then, create your $scope.options_scn_cst object.

maxYvalue2().then(function(maxYvalue) {
    // Now that we know maxYvalue, define the scope variable
    $scope.options_scn_cst = {...}
})

This of course requires that the <nvd3> directive that you use watches over its options binding to detect that the variable is there once it is defined.

If it is no the case and the nvd3 is your directive, you can use $scope.$watch('options', function() {...})

If it is not the case and the nvd3 directive is not yours, you could surround it in some ng-if element to only display it once options_scn_cst exists:

<nvd3 ng-if="options_scn_cst" data="data_scn_cst" options="options_scn_cst"></nvd3>
Comments