Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does Angular clear the $watch?

Tags:

angularjs

I understand that each model that I include in my view enters the digest loop and $watch applied on it, since all Angular applications are basically one page apps. But when does it clear the $watch?

For example, let's say that I have the page view1.html with the template {{view.name1}}. When I switch the route to the page view2.html with the template {{view.name2}}, does the $watch on {{view.name1}} is being unregistered automatically or should I do it manually?

like image 779
emc Avatar asked Nov 09 '14 15:11

emc


People also ask

How to stop or deactivate the watch in AngularJS?

When you invoke the $watch() method, to create a binding, Angular JS returns a "de-registration" function. This function can then be used to unbind your $watch() listener - all you have to do is invoke this returned function and your $watch() listener will be removed. Save this answer.

What are angular watchers?

8,000+ users. Check how many watchers are active in an angular app. Angular watchers is the ultimate AngularJS tool which tells you how many active watchers you currently have. It automatically updates so you can see live how many watcher a page have. This is perfect to increase performance and debugging as well.

Why migrate from AngularJS to Angular?

Mobile Support: With AngularJS even today you can build dynamic web pages it would lack support for mobile browsers. However, Angular offers support across mobile devices & browsers. Therefore, the migration ensures support for most kinds of mobile browsers and devices.


1 Answers

This answer has links to angular scopes source code,

Each scope have a private array $$watchers:

  • When the method $watch is called it pushes listeners into $$watchers, see Scope#$watch.
  • With each $digest it iterates down all the $$watchers, see Scope#$digest.
  • When the scope method $destroy is called it cleans up all it's watchers, see Scope#$destroy
  • Each scope also broadcast $destroy to all of it's child scopes either isolated or not, so you'll never have an orphan scope.
  • Angular listens for DOM node removal and triggers $destroy for all directive scopes ( that are created within the $compile service), see here

Angular automatically calls $destroy on these cases:

  • https://github.com/angular/angular.js/blob/v1.3.2/src/ng/directive/ngIf.js#L111
  • https://github.com/angular/angular.js/blob/v1.3.2/src/ng/directive/ngInclude.js#L206
  • https://github.com/angular/angular.js/blob/v1.3.2/src/ng/directive/ngRepeat.js#L389
  • https://github.com/angular/angular.js/blob/v1.3.2/src/ng/directive/ngSwitch.js#L160
  • https://github.com/angular/angular.js/blob/v1.3.2/src/ngRoute/directive/ngView.js#L205

You'll only need to call $destroy when you manually create scopes ($new / $transclude) and want them to be destroyed before their parent scope.

ngView is probably a good example because you have only one element that is bound to it in your application and that element (with it's scope which often is the rootScope) is never destroyed. So angular automatically creates a new child scope($new) when it enters a route and calls $destroy on it when exists thus flushing all the watchers which were created by that route.

From Scope#$new docs:

$destroy() must be called on a scope when it is desired for the scope and its child scopes to be permanently detached from the parent and thus stop participating in model change detection and listener notification by invoking.

From $compile - transclusion functions docs:

if you intend to add and remove transcluded content manually in your directive (by calling the transclude function to get the DOM and and calling element.remove() to remove it), then you are also responsible for calling $destroy on the transclusion scope.


Take this as a rule, If you manually created a scope (with $new or $transclude) and it is not needed anymore but it's parent scope does you need to manually destroy it.

like image 154
Ilan Frumer Avatar answered Sep 18 '22 12:09

Ilan Frumer