如何在异步函数之外设置 var 以在 $scope 对象中使用

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

在过去的两天里,我一直在阅读有关承诺、回调和生成器的文章,试图找出如何从异步函数中设置一个值,然后我可以在 $scope 对象中使用该值。

我无法得到解决 var 的承诺,它只是 returns 承诺而不是价值,根据我的理解,这是它应该做的。这就是我认为发电机可能会有所帮助的地方?

那么,如何从异步函数设置 var 以便我可以在对象 $scope.options_scn_cst

中使用 var

这是专门针对 nvd3 的,正如我正在尝试做的那样,循环遍历环回函数 Rpt_scn_cost_v 的结果以找到最大值,然后将其设置为最大值nvd3 的 yDomain: [min, max] 中的 Y 轴。

我的代码现在是这样的:

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'
            }
        }
    };

然后我这样调用 $scope 对象:

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

我也使用 $q 尝试过这种方式,但它 returns 承诺而不是价值...

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)

Rpt_scn_cost_v.find returns 一个承诺,我想。这使您可以链接承诺并使用结果:

function maxYvalue2() {
    return Rpt_scn_cost_v.find({filter: { where: {scenario_id: $stateParams.id}}}).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;
    });
}

使用者:

maxYvalue2().then(function(maxYvalue) {
    console.log('maxYvalue=', maxYvalue);
});

因为您的代码本质上是异步的,所以无论您尝试哪种方法,您都永远不会将它同步写入您的 var。

您有几种方法可以解决这个问题。一种选择是等到 promise 解决(使用其 then 方法),然后,并且只有在那时,创建您的 $scope.options_scn_cst 对象。

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

这当然需要您使用的 <nvd3> 指令监视它的 options 绑定以检测变量在定义后是否存在。

如果不是这种情况并且 nvd3 是你的指令,你可以使用 $scope.$watch('options', function() {...})

如果不是这种情况并且 nvd3 指令不是您的,您可以将其包围在某些 ng-if 元素中,以便仅在 options_scn_cst 存在时显示它:

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