Cherry
Cherry

Reputation: 33628

How check whether variable have already been watched in angularjs?

This code reacts on variable my_var changes in scope:

    $scope.$watch('my_var', function () {
        //do somethins
    });

Is there a way to check whether my_var is being watched or not? E.g. have somebody already called $scope.$watch function on my_var or not?

Upvotes: 0

Views: 278

Answers (3)

Ralph
Ralph

Reputation: 1699

You can use something like this:

function isWatched($scope, ref) {
    for(var i = 0; i < $scope.$$watchers.length; i++) {
        const w = $scope.$$watchers[i];
        if (w && w.exp === ref)
            return true;
    }
    return false;
}

$scope.$watch('my_var', function () {
    //do somethins
});

var result = isWatched($scope, 'my_var');

Upvotes: 0

Petr Averyanov
Petr Averyanov

Reputation: 9486

This may help.

let myVar = $scope.my_var;
Object.defineProperty($scope, 'my_var', {
    get: function() {
        console.log('Someone called me');
        return myVar;
    },
    set: function(val) {
        myVar  = val;
    }
});
$scope.$apply();

If this variable is being watched - you will see something in log. (Of course you may have some access from your js code, but you can debug ... Also this should be $scope, where variable is actuall defined)

Upvotes: 1

Aleksey Solovey
Aleksey Solovey

Reputation: 4191

You can simply list all of your watchers and check if your variable has a watcher. I don't think there are any other ways to check if $scope.$watch already applied on it.

Here is the code that you can paste even in your console to check your watchers:

function getWatchers(root) {
  root = angular.element(root || document.documentElement);
  var watcherCount = 0;

  function getElemWatchers(element) {
    var isolateWatchers = getWatchersFromScope(element.data().$isolateScope);
    var scopeWatchers = getWatchersFromScope(element.data().$scope);
    var watchers = scopeWatchers.concat(isolateWatchers);
    angular.forEach(element.children(), function(childElement) {
      watchers = watchers.concat(getElemWatchers(angular.element(childElement)));
    });
    return watchers;
  }

  function getWatchersFromScope(scope) {
    if (scope) {
      return scope.$$watchers || [];
    } else {
      return [];
    }
  }
  return getElemWatchers(root);
}

console.log(getWatchers())
// this prints the array of watchers, e.g:
// [ {fn: ƒ, last: "my_var", get: ƒ, exp: ƒ, eq: false} ]

The code is taken from "Watching your AngularJS Watchers" by Kent C. Dodds

(The code was modified to print watchers, instead of just displaying how many are used (array length), so be prepared if you have more that 1000+ watchers)

Upvotes: 1

Related Questions