在服务计算时,角度范围不会更新

时间:2015-05-27 07:03:57

标签: javascript angularjs

我在服务中有一个函数需要很长时间才能计算,所以我想在范围上显示一条消息来显示它的计算结果。 我在这里创建了一个(简化的)jsfiddle:http://jsfiddle.net/rikboeykens/brwfw3g9/

var app = angular.module('myApp', []);

app.service('testService', function(){
    this.longFunction=function(){
        for (var i=0; i<1000000000;i++){


        }
    }
});

function TestCtrl($scope, testService)
{
    $scope.$apply(function(){$scope.waiting="not waiting";});
    $scope.longFunction = function(){
        $scope.waiting="waiting";
        testService.longFunction();
        $scope.waiting="not waiting";
    }
}

testService上的longFunction大约需要两秒钟才能完成,但$ scope.waiting在发生这种情况时不会更新为“等待”。

我尝试使用$ scope。$ apply然后我得到一个错误,说$ apply已经在进行中。

如果我在testService上异步执行longFunction,它会起作用吗?我一直在研究使用promises,但我不确定如何实现它们。

3 个答案:

答案 0 :(得分:2)

您可以使用$timeout

function TestCtrl($scope, testService, $timeout)
{
   $scope.waiting="not waiting";
    $scope.longFunction = function(){
        $scope.waiting="waiting";
        $timeout(function(){
          testService.longFunction();
          $scope.waiting="not waiting";
        })
    }
}

答案 1 :(得分:1)

它正常工作,但您没有看到waiting消息,因为longFunction同步运行,我怀疑它的执行会阻止UI被绘制以显示waiting消息更新。当longFunction调用结束时,UI线程不忙,并设置"not waiting"消息,使您无法阅读"waiting“文本。

这是Web浏览器中的预期行为,因为所有内容都在UI线程中执行,如果操作是同步的并且UI被冻结了一段时间,则没有Web浏览器可以优先处理工作。由于长for循环或长计算会占用大量CPU资源,因此Web浏览器需要等到操作结束才能继续绘制屏幕。

您可以在Angular中使用setTimeout flavor来模拟异步操作,这将优先使用UI,您将能够看到消息更改:

$scope.longFunction = function(){
        $scope.waiting="waiting"; 

        // Actually this is a workaround, because JS doesn't provide
        // an elegant way of enqueueing asynchronous operations in the UI
        // layer. BTW, does Web Workers mean something for you? ;)
        $timeout(function() {
            testService.longFunction();
        }, 0);

        $scope.waiting="not waiting";
}

答案 2 :(得分:1)

你肯定要超时执行服务功能。我在Codeopen.io上创建并编写了示例:http://codepen.io/skymk/pen/EjNpKL?editors=101

app.controller('Controller', ['$scope', 'testService', '$timeout',  function($scope, testService, $timeout) {
    $scope.waiting="not waiting";
    $scope.longFunction = function() {
        $scope.waiting="waiting";
        $timeout(function() {
          testService.longFunction();
          $scope.waiting="not waiting";
        }, 0);    
    }
    $scope.longFunction()
}])