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
    });
}

コントローラーにサービスの変更を反映させるにはどうすればよいですか? サービスまたはコントローラーで何か問題があったかどうかはわかりませんが、機能しません。

4

3 に答える 3

2

data プロパティはプリミティブであるためint、値がコピーされますscope.data。現在、これらは 2 つの個別の値であり、1 つはサービスに保存され、もう 1 つはコントローラーに保存されています。したがって、サービス データが変更されても、コントローラ データ プロパティには影響しません。

それらを同期させるには、サブプロパティを持つオブジェクトを使用します。したがって、データ宣言はサービス中になります

data:{value:0}

そして、式をバインドする場所はどこでも使用しますdata.value

于 2013-08-21T12:17:39.937 に答える
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 でsetTimeoutfor とにかくを使用することをお勧めします。setIntervalsetInterval

このトピックについて深く掘り下げたくはありませんが、優先する理由に興味がある場合はsetTimeoutsetIntervalこのトピックに関する John Resig の投稿をお勧めします。

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

また、Angular のデータ バインディングがどのように機能するかの詳細については深く掘り下げたくありません。このトピックに関する優れた回答がここ SO に既にいくつかあるためです。

リンク:

AngularJS でデータ バインディングはどのように機能しますか?

于 2013-08-21T12:59:17.893 に答える
0

Chandermani の分析は正しい。サービスを変更する以外の別のオプションは、代わりに値を返す関数を持つようにコントローラーを変更することです。たとえば`

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)て変更するために を使用する必要があることです。

于 2013-08-21T12:31:29.033 に答える