【问题标题】:Binding promise data to $scope将承诺数据绑定到 $scope
【发布时间】:2014-04-23 05:02:04
【问题描述】:

我设计了一个从 url 获取数据并将其返回给控制器的工厂。 在控制器中,我打电话给这家工厂。 我已经使用 $q 来解决承诺。 从控制器调用工厂时,我试图将返回的值分配给范围。 在我尝试访问范围内的值时分配值后,我收到未定义的消息 你能帮我解决这个问题吗

app.factory('barchart', function($http,$q) {
    var factory={};
    factory.drawChart=function() {  
        var deferred=$q.defer();
        $http({
            method: 'GET',
            url: 'ActionServlet',
            headers: {'Content-Type': 'application/json' },
            params: {country: "densityplot"}
        })
        .success(function (data, status, headers, config) {
            deferred.resolve(data);
        })
        .error(function (data, status, headers, config) {
            // something went wrong :(
        });
        return deferred.promise;
        };
    return factory;
});

app.controller('mycontroller',function($scope, $http, barchart) {
    var promise = barchart.drawChart();
    console.log("Promise " + promise);
    promise.then(function(data) {
        $scope.barChartData = data;
        console.log("barchart data " + $scope.barChartData.getSVG());
    });
        console.log("barchart data " + $scope.barChartData.getSVG());
});

但是当它在范围内时,它会显示数据。 每当我尝试在承诺范围之外打印值时,它都会出错。

【问题讨论】:

    标签: angularjs angularjs-scope


    【解决方案1】:

    Angular's $http 执行异步操作。你的then如下

    promise.then(function(data) {
        $scope.barChartData = data;
        console.log("barchart data " + $scope.barChartData.getSVG());
    });
    

    $http 完成异步操作后接收数据。它将数据放入变量中并打印出来,一切正常。

    但是,当您尝试在该范围之外登录时

    promise.then(function(data) {
        $scope.barChartData = data;
        console.log("barchart data " + $scope.barChartData.getSVG());
    });
    console.log("barchart data " + $scope.barChartData.getSVG());
    

    $http 的操作尚未完成,因此$scope.barChartData 仍未定义。

    您的then 只是告诉控制器在收到工厂的承诺时要做什么。仅仅因为那段代码在单独的日志之上并不意味着它会按该顺序被调用。

    【讨论】:

    • 上面的代码可以同步吗?就像只有在从远程服务器接收到范围后才应该为范围分配值?
    • @kais 这就是then 函数的作用,它在服务完成远程调用时执行,并将承诺返回给控制器
    • 我需要的是promise的值应该在编写代码的顺序中可用。因为我希望在jasmine中测试范围内的值
    • 当我尝试访问 jasmine 中的同一个范围变量时,它显示未定义。所以我可以延迟一段时间,以便将数据分配给范围并立即访问吗?
    • @kais 测试返回承诺的服务是一个完全不同的主题,最好为此创建一个单独的问题。至少你知道为什么它没有按照你的预期做,所以你可以从那里开始工作:-)
    【解决方案2】:

    问题是在 promise 返回之前触发了超出 promise 范围的控制台语句......因此未定义......

    app.controller('myController', function($scope, barchart) {        
        barchart.drawChart()
            .then(function(data) {
                $scope.barChartData = data;
                console.log("barchart data " + $scope.barChartData.getSVG());
            });
    
        console.log("barchart data " + $scope.barChartData.getSVG());
    });
    

    另一方面……您的 $http 服务实际上是否返回了一个函数对象?这看起来很奇怪,但并非不可能:

    $scope.barChartData.getSVG();
    

    如果您对 asynchronousityJS 的工作方式感到困惑,您应该进一步阅读该主题,但简而言之,您的代码运行方式是这样的。不服用

    1. barchart.drawChart()
    2. $http(); //工厂函数
    3. console.log("承诺" + 承诺);
    4. console.log("条形图数据" + $scope.barChartData.getSVG()); //then()之外的那个
    5. 在我们等待 http req 作为异步请求时可能需要等待一些时间,但我们永远不知道返回值所需的确切时间 - 这就是 Promise 的亮点!
    6. 那么()
    7. $scope.barChartData = 数据; //在承诺中
    8. console.log("条形图数据" + $scope.barChartData.getSVG()); //在promise里面

    您在评论中说,当承诺返回良好时,您希望外部触发,您可以通过另一个承诺来完成此操作。

    app.controller('myController', function($scope, $q, barchart) {        
         var requestFinished = $q.defer();
    
         barchart.drawChart()
            .then(function(data) {
                $scope.barChartData = data;
                console.log("barchart data " + $scope.barChartData.getSVG());
                requestFinished.resolve();
            });
    
         requestFinished.promise.then(function() {
             console.log("barchart data " + $scope.barChartData.getSVG());
         });
    });
    

    【讨论】:

    • 上面的代码可以同步吗?就像只有在从远程服务器接收到范围后才应该为范围分配值?
    • 但它没有按我想要的方式工作。它没有在控制台中显示外面的即时语句。我希望它的数据在外面分配后立即显示。有可能吗?
    猜你喜欢
    • 2015-01-13
    • 2017-11-16
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 2021-03-28
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    相关资源
    最近更新 更多