Angular Bad Parts, part 2

Transparent scope and "referential hell" mean that you CANNOT KNOW what part of the system will be updated when you introduce a change using $scope.$apply().

You have no guarantees.

This is a design tradeoff.

Do you know that each time you call $scope.$apply() you actually call $rootScope.$apply()?

And this call updates all scopes and run all your watches?

Moreover, $rootScope.$apply() is called each time when:

  1. $timeout handler is invoked (almost all debounce services are broken by design)
  2. $http receives a response (yeah, if you have a polling implemented on $http ...)
  3. any DOM handler is called (have you throttled your ng-mouseovers? They actually invoke ALL your $watches, and built-in digest phasing does not really help)

If you know, that some change is localised (like, if you click the button, only the same $scope will be affected), then you MUST use $scope.$digest.
But again, you will face nasty "$digest is already in progress" issue...