ChatGPT解决这个技术问题 Extra ChatGPT

AngularJS : Clear $watch

I have a watch function in my AngularJS application.

$scope.$watch('quartzCrystal', function () {
   ...
}

However, after some condition (in my example, changing the page at my single-page application) I want to stop that watch (as like clearing timeout).

How can I do that?


P
Peter Mortensen

$watch returns a deregistration function. Calling it would deregister the $watcher.

var listener = $scope.$watch("quartz", function () {});
// ...
listener(); // Would clear the watch

Do you know if it's a good practice to deregister all your listeners at the end of a controller lifecycle (like on a $on('$destroy')) or AngularJS will take care of them? thanks!
All watchers will be removed when the scope is destroyed, you don't need to manage those
You can see an interesting discussion here that explains the matter: github.com/angular/angular.js/issues/4574 Basically, if you assign a listener to the $rootScope, you have to unassign it your self, or it will persist through $scope changes. Watchers on $scope get destroyed with the $scope ($scopes are not singletons in Angular, and they get created and destroyed when needed).
But, what if i only want the watcher for checking if the value exists and then when it exists do some changes and then de register itself i already tried - var listen = $scope.$watch('mvIdentity.currentUser', function(currentUser) { test = 1; console.log("--> " + $scope.updateemail + " -- " + test); listen(); });
@UmurKontacı Actually deadman's comment is perfectly valid as your original comment is not correct for every case.
A
Anders Ekdahl

scope.$watch returns a function that you can call and that will unregister the watch.

Something like:

var unbindWatch = $scope.$watch("myvariable", function() {
    //...
});

setTimeout(function() {
    unbindWatch();
}, 1000);

Yes, you're able to unbind within the watchFn! Simple use-case: you want to watch and execute the watchFn only once, then stop watching.
Am I able to rebind the watch after I call the unbind function, like calling it again?
This was useful. Doing the unbindWatch in a timeout seems important in my testing.
In this case you should use $timeout, which you can also de-register!
Best to avoid timeouts
S
SoEzPz

You can also clear the watch inside the callback if you want to clear it right after something happens. That way your $watch will stay active until used.

Like so...

var clearWatch = $scope.$watch('quartzCrystal', function( crystal ){
  if( isQuartz( crystal )){
    // do something special and then stop watching!
    clearWatch();
  }else{
    // maybe do something special but keep watching!
  } 
}

n
naCheex

Some time your $watch is calling dynamically and it will create its instances so you have to call deregistration function before your $watch function

if(myWatchFun)
  myWatchFun(); // it will destroy your previous $watch if any exist
myWatchFun = $scope.$watch("abc", function () {});

M
Manish Kumar

Ideally, every custom watch should be removed when you leave the scope.

It helps in better memory management and better app performance.

// call to $watch will return a de-register function
var listener = $scope.$watch(someVariableToWatch, function(....));

$scope.$on('$destroy', function() {
    listener(); // call the de-register function on scope destroy
});

D
Danilo Cândido

If you have too much watchers and you need to clear all of them, you can push them into an array and destroy every $watch in a loop.

var watchers = [];
watchers.push( $scope.$watch('watch-xxx', function(newVal){
   //do something
}));    

for(var i = 0; i < watchers.length; ++i){
    if(typeof watchers[i] === 'function'){
        watchers[i]();
    }
}

watchers = [];