Angular - 更改Factory数据时更新范围

时间:2014-10-20 06:03:12

标签: javascript angularjs

我正在使用工厂来轮询特定的网络服务。此Web服务用于更新任何工厂的数据。我在主控制器中启动此工厂,并通过工厂函数填充范围变量。该变量正确初始化,我在屏幕上获得了正确的数据,但我却在努力使数据自动绑定。

编辑其他备注: 此代码在Factory中的原因是我计划在多个视图中使用工厂数据。

这是我到目前为止所做的:

App.factory('metrics', function($http, $q, $timeout){
    var service;
    var users = [{laps:[]}];
    var updateMetrics = function(){
        //updates the users array in the factory
    };
    service.load = function (){
        var deferred = $q.defer();

        $http.get('http://www.example.com/api/random').success(function(data) {
            var temp_array = data.split("\n");
            updateMetrics(0, temp_array);
            deferred.resolve({status: 'good'});
            $timeout(service.load,3000);
        });
        return deferred.promise;
    };

    service.lastLapInfo = function(){
        var lastlap = [];
        for (var i=0; i<users.length;i++)
        {
            var lap = users[i].laps[users[i].laps.length-1];
            lastlap.push(lap);
        }
        return lastlap;
    };
    return service;
});

App.controller('mainController', function($scope, metrics) {
    metrics.load().then(function(response){
        $scope.$watch(function () { return metrics.lastLapInfo() }, function (newVal, oldVal) {
            if (newVal !=oldVal)
            {
                $scope.users=metrics.lastLapInfo();
            }
        });
    });
});

当我尝试上述操作时,我收到一条错误消息,表示&#39; 10 $ digest()迭代已到达&#39;。我不知道这是怎么可能的,因为我没有多次调用监视功能。

有任何建议(或其他方法来完成我尝试做的事情吗?)

1 个答案:

答案 0 :(得分:2)

如果您没有100%使用$watch设置,我更喜欢的模式是将新模块(不是引用)的实例绑定到当前范围,并将控制器严格保留为使用的组件用于将项目的视图和模型连接在一起。这排除了$watch的使用,即使是跨模块协调数据也是如此。我更喜欢在模块/工厂中使用$rootScope的{​​{1}},$broadcast$emit方法(在传递$on作为服务之后可能会或可能不会适用于所有情况,尽管它适用于我所遇到的所有情况,而不是相对缓慢的$rootScope$watch方法。使用后者让我觉得内心很脏...但我离题了。

在你的情况下会有类似的事情吗?

$watchCollection

通过设置App.factory('metrics', function($http, $q, $timeout){ var service; service.users = [{laps:[]}]; service.updateMetrics = function(){ // updates the users array in the current instance of `metrics` // ex: // this.users = updatedMetrics; // don't do: // service.users = updatedMetrics; }; service.load = function (){ var deferred = $q.defer(); $http.get('http://www.example.com/api/random').success(function(data) { var temp_array = data.split("\n"); this.updateMetrics(0, temp_array); deferred.resolve({status: 'good'}); $timeout(service.load,3000); }.bind(this)); return deferred.promise; }; service.lastLapInfo = function(){ var lastlap = []; for (var i=0; i<this.users.length;i++) { var lap = this.users[i].laps[this.users[i].laps.length-1]; lastlap.push(lap); } return lastlap; }; return service; }); App.controller('mainController', function($scope, metrics) { $scope.metrics = angular.copy(metrics); $scope.metrics.load(); }); ,我们正在创建$scope.metrics = angular.copy(metrics)的新实例,而不是将metrics设置为对$scope.metricsmetrics)的引用。这有几个好处,包括您现在可以在控制器中使用同一模块的多个实例(即$scope.metrics = metrics,因为绑定到$scope.foo = angular.copy(foo); $scope.bar = angular.copy(foo);的对象是完全新对象,而不是对同一模块的引用。

另一个好处是,附加到$scope的{​​{1}}实例可用于调用metrics上的方法,这些方法可以允许$scope的任何更改自动应用于你的控制器的观点。在不使用metricsmetrics时尝试使其工作时,我经常遇到一些奇怪的问题,似乎是因为angular.copy附带的引用模块的更改并不总是被注册。