angularjs $ watch的替代方案可以触发ui从服务中更改

时间:2014-09-17 20:32:11

标签: angularjs service

我想知道是否有不同的方法来使用$ watch来实现以下目标。

设定: ControllerA依赖于ServiceA。 ControllerB依赖于ServiceB。 当前浏览器视图显示两个控制器。

方案: ControllerA正在ServiceA上启动一个函数,它又改变了ServiceB中的属性X的值,这应该反映在ControllerB的UI中。

http://jsfiddle.net/zexscvax/2/

HTML:

<div>
    <div ng-controller="ControllerA"></div>
    <div ng-controller="ControllerB">Progress: {{progress}}</div>
</div>

JS:

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

myApp.factory('serviceA', ['$q', '$interval', 'serviceB', function ($q, $interval, serviceB) {

    var service = {};

    service.start = function () {
        var progress = 0;
        var deferred = $q.defer();
        deferred.promise.then(null,null, notifyServiceB);

        function notifyServiceB() {
          serviceB.update(progress);
        }

        $interval(function() { 
          if (progress == 0.99) {
            deferred.resolve();
          } else {
            progress += 0.01; 
            deferred.notify(progress); 
          }
        }, 50, 100);   
    };

    return service;

}]);

myApp.factory('serviceB', ['$rootScope', function ($rootScope) {

    var service = {};

    service.update = function (progress) {
        console.log('update', progress);
        service.progress = progress;
        //$rootScope.$apply(); // <+ ERROR: $digest already in progress
    };

    return service;

}]);

myApp.controller('ControllerA', ['$scope', 'serviceA',
function ($scope, serviceA) {
    serviceA.start();
}]);

myApp.controller('ControllerB', ['$scope', 'serviceB',
function ($scope, serviceB) {
    $scope.progress = serviceB.progress;

    /* this works but I'm not sure whether this is performing

    $scope.$watch(function () { return serviceB.progress; },
        function (value) {
            $scope.progress = serviceB.progress;
        }
    );
    */
}]);

如果没有ControllerB中的$ watch用于ServiceB中的属性X,UI将不会更新。我也尝试在ServiceB中注入$ rootScope以运行apply(),但这不起作用。

我不完全确定是否有更好的方法来设置此场景或者$ watch是否正常。我有点担心性能问题,因为属性X的值几乎每50毫秒变化一次(它基本上是一个可视化计时器倒计时)。

感谢您的意见。

1 个答案:

答案 0 :(得分:1)

如果您不使用$ watch,您可以使用$ rootScope进行广播,而在控制器B上,您可以使用$ on此事件并处理视图更新。