2013-08-21 37 views
0

在我的應用我想有一個自我更新的數據服務,其被注入到控制器:自我更新服務注入到控制器

app.factory("StatsService", function() { 
    var service; 
    service = { 
     data: 0, 
     init: function() { 
      var self = this; 
      setInterval(function() { 
       self.data = Math.floor((Math.random() * 100) + 1); 
      }, 1000); 
     } 
    }; 
    service.init(); 
    return service; 
}); 

下面是一個例子控制器:

app.controller("SourcesController", ['$scope', 'StatsService', function($scope, StatsService) { 
    $scope.data = StatsService.data; 

    $scope.$watch('data', function(val) { 
     // this does not work either 
    }); 
} 

如何讓控制器反映服務更改?我不知道我是否在服務或控制器方面做了錯誤,但它不起作用。

回答

1

您的代碼存在的問題是setInterval()發生在Angular世界之外。如果你修改Angular世界以外的東西,那麼框架並不知道這個變化。在這種情況下,您需要將代碼包裝到$apply調用中,以通知框架。

app.factory("StatsService", ['$rootScope', function($rootScope) { 
    var service; 
    service = { 
     data: 0, 
     init: function() { 
      var self = this; 
      setInterval(function() { 
       $rootScope.$apply(function(){ 
        self.data = Math.floor((Math.random() * 100) + 1); 
       }); 
      }, 1000); 
     } 
    }; 
    service.init(); 
    return service; 
}]); 

通常情況下,您不必擔心Angular會將大部分事物掛鉤,導致狀態更改。例如,如果您使用的是setTimeout而不是setInterval,那麼您可以使用Angular的$timeout服務,該服務將反過來通知幕後的框架,以便您不必這樣做。無論如何,在JavaScript中使用setTimeout贊成setInterval實際上是一個好主意,因爲setInterval的調用可能是非確定性的。

我不想太深入瞭解這個話題,但如果你有興趣,爲什麼青睞setTimeout超過setInterval我推薦的話題約翰Resig的帖子:

http://ejohn.org/blog/how-javascript-timers-work/

我也不要」不想潛入的角度的數據綁定如何工作的,已經有關於這一主題在這裏的一些偉大的答案,在這樣的細節:

鏈接:

How does data binding work in AngularJS?

+0

大多數情況下,您希望使用'$ timeout'服務來代替。 –

+0

的確,使用setInterval更好。 – Christoph

+0

'$ timeout'消除了'$ rootScope'依賴嗎? – acid

2

由於數據屬性是原始的int,因此將值複製到您的scope.data。現在這些是兩個獨立的值,一個存儲在服務器中,另一個存儲在控制器中。所以即使服務數據發生變化,它也不會影響控制器數據屬性。

爲了保持同步使用對象與子properties.So數據申報,在服務變得

data:{value:0} 

而且在任何你綁定使用表達data.value

+0

我在我的服務中更改了'service = {data.value = 0}',在我的控制器中'$ scope.data = StatsService.data.value',它不起作用。 – acid

+0

@acid因爲你必須回到原來的問題。如果你的控制器具有'data = StatsService.data',那麼_reference_將是相同的,你將能夠通過'scopedata.value'訪問該值並且手錶訪問'data.value',否則你是,再次,只是複製原始值。 –

+0

謝謝@SimonBelanger,你高聲指出原因:) – Chandermani

0

Chandermani是正確的,他的分析。另一個選擇而不是改變你的服務是改變你的控制器有一個函數,而不是返回值。對於example`

app.controller("SourcesController", ['$scope', 'StatsService', function($scope, StatsService) { 
    $scope.data = function(newValue) { 
    if(arguments.length === 0) return StatsService.data; 
    StatsService.data = newValue; 
    } 

    $scope.$watch('data()', function(val) { 
    }); 
} 

的不便之處是,你必須在你的綁定來訪問值使用data()data(value)去改變它。

+0

我不介意改變服務,但是如同指出的[在這個評論](http://stackoverflow.com/questions/18356840/self-updating-service-injected-to-the - 控制器#comment26950844_18357202)我不認爲這是事實。或者我做錯了什麼。 :) – acid

+1

@acid這是一個單獨的問題。克里斯托弗在他的帖子中迴應了這個。 –