424 Stimmen

AngularJS : Wie kann man Dienstvariablen überwachen?

Ich habe einen Dienst, sagen wir:

factory('aService', ['$rootScope', '$resource', function ($rootScope, $resource) {
  var service = {
    foo: []
  };

  return service;
}]);

Und ich würde gerne foo um eine Liste zu steuern, die in HTML gerendert wird:

<div ng-controller="FooCtrl">
  <div ng-repeat="item in foo">{{ item }}</div>
</div>

Damit der Controller erkennen kann, wann aService.foo aktualisiert wird, habe ich dieses Muster zusammengeschustert, bei dem ich einenService zum Controller hinzufüge $scope und verwenden Sie dann $scope.$watch() :

function FooCtrl($scope, aService) {                                                                                                                              
  $scope.aService = aService;
  $scope.foo = aService.foo;

  $scope.$watch('aService.foo', function (newVal, oldVal, scope) {
    if(newVal) { 
      scope.foo = newVal;
    }
  });
}

Das fühlt sich langatmig an, und ich habe es in jedem Controller wiederholt, der die Variablen des Dienstes verwendet. Gibt es einen besseren Weg, um die Überwachung gemeinsamer Variablen zu erreichen?

2voto

Justus Wingert Punkte 462

Für diejenigen, die wie ich nur auf der Suche nach einer einfachen Lösung, dies tut fast genau das, was Sie erwarten, mit normalen $watch in Controllern. Der einzige Unterschied ist, dass es die Zeichenfolge in seiner Javascript-Kontext und nicht auf einen bestimmten Bereich auswertet. Sie müssen $rootScope in Ihrem Dienst injizieren, obwohl es nur verwendet wird, um in den Digest-Zyklen richtig Haken.

function watch(target, callback, deep) {
    $rootScope.$watch(function () {return eval(target);}, callback, deep);
};

2voto

Atais Punkte 9937

Ich habe in einem anderen Thread eine wirklich tolle Lösung für ein ähnliches Problem gefunden, allerdings mit einem völlig anderen Ansatz. Quelle: AngularJS : $watch innerhalb der Direktive funktioniert nicht, wenn der $rootScope-Wert geändert wird

Grundsätzlich die Lösung dort sagt NICHT ZU verwenden. $watch da es sich um eine sehr schwere Lösung handelt. Stattdessen Sie schlagen vor, Folgendes zu verwenden $emit$on .

Mein Problem war, dass Uhr eine Variable in meinem Dienstleistung und reagieren in Richtlinie . Und mit der obigen Methode ist es sehr einfach!

Mein Modul/Dienst-Beispiel:

angular.module('xxx').factory('example', function ($rootScope) {
    var user;

    return {
        setUser: function (aUser) {
            user = aUser;
            $rootScope.$emit('user:change');
        },
        getUser: function () {
            return (user) ? user : false;
        },
        ...
    };
});

Also grundsätzlich Uhr meine user - wenn er auf einen neuen Wert I gesetzt wird $emit a user:change Status.

In meinem Fall, in der Richtlinie Ich habe:

angular.module('xxx').directive('directive', function (Auth, $rootScope) {
    return {
        ...
        link: function (scope, element, attrs) {
            ...
            $rootScope.$on('user:change', update);
        }
    };
});

Jetzt im Richtlinie Ich höre auf dem $rootScopeauf die gegebene Veränderung - ich reagiere entsprechend. Sehr einfach und elegant!

2voto

honkskillet Punkte 2643

Ich kam zu dieser Frage, aber es stellte sich heraus, dass mein Problem war, dass ich setInterval verwendet wurde, wenn ich die angular $interval Anbieter verwendet haben sollte. Dies ist auch der Fall für setTimeout (verwenden Sie $timeout statt). Ich weiß, es ist nicht die Antwort auf die OP's Frage, aber es könnte einige helfen, wie es mir geholfen.

2voto

chandings Punkte 549

Während ich ein sehr ähnliches Problem hatte, beobachtete ich eine Funktion im Bereich und ließ die Funktion die Dienstvariable zurückgeben. Ich habe eine Paukerei . Sie können den Code unten finden.

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

myApp.factory("randomService", function($timeout){
    var retValue = {};
    var data = 0;

    retValue.startService = function(){
        updateData();
    }

    retValue.getData = function(){
        return data;
    }

    function updateData(){
        $timeout(function(){
            data = Math.floor(Math.random() * 100);
            updateData()
        }, 500);
    }

    return retValue;
});

myApp.controller("myController", function($scope, randomService){
    $scope.data = 0;
    $scope.dataUpdated = 0;
    $scope.watchCalled = 0;
    randomService.startService();

    $scope.getRandomData = function(){
        return randomService.getData();    
    }

    $scope.$watch("getRandomData()", function(newValue, oldValue){
        if(oldValue != newValue){
            $scope.data = newValue;
            $scope.dataUpdated++;
        }
            $scope.watchCalled++;
    });
});

2voto

elitechance Punkte 51

Hier ist mein allgemeiner Ansatz.

mainApp.service('aService',[function(){
        var self = this;
        var callbacks = {};

        this.foo = '';

        this.watch = function(variable, callback) {
            if (typeof(self[variable]) !== 'undefined') {
                if (!callbacks[variable]) {
                    callbacks[variable] = [];
                }
                callbacks[variable].push(callback);
            }
        }

        this.notifyWatchersOn = function(variable) {
            if (!self[variable]) return;
            if (!callbacks[variable]) return;

            angular.forEach(callbacks[variable], function(callback, key){
                callback(self[variable]);
            });
        }

        this.changeFoo = function(newValue) {
            self.foo = newValue;
            self.notifyWatchersOn('foo');
        }

    }]);

In Ihrem Controller

function FooCtrl($scope, aService) {
    $scope.foo;

    $scope._initWatchers = function() {
        aService.watch('foo', $scope._onFooChange);
    }

    $scope._onFooChange = function(newValue) {
        $scope.foo = newValue;
    }

    $scope._initWatchers();

}

FooCtrl.$inject = ['$scope', 'aService'];

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X