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

时间:2016-11-17 21:25:23

标签: javascript angularjs asynchronous nvd3.js

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

我无法接受解决然后到var的承诺,它只返回承诺而不是值,这是我应该根据我的理解做的。这是我认为也许发电机可能有帮助的地方?

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

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

我的代码现在看起来像这样:

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,但它会返回承诺而不是值......

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)

2 个答案:

答案 0 :(得分:2)

我假设

File.write('foo.yaml', bar.to_yaml) 会返回一个承诺。这使您可以链接承诺并使用结果:

Rpt_scn_cost_v.find

使用者:

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

答案 1 :(得分:1)

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

您有几种方法可以解决这个问题。一种选择是等到promise解析(使用其$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指令不属于您,则可以将其包围在某个<nvd3 ng-if="options_scn_cst" data="data_scn_cst" options="options_scn_cst"></nvd3> 元素中,只有在options_scn_cst存在时才显示它:

MyFormText