This repository has been archived by the owner on Apr 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 27.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Scope): async auto-flush $evalAsync queue when outside of $digest
This change causes a new $digest to be scheduled in the next tick if a task was was sent to the $evalAsync queue from outside of a $digest or an $apply. While this mode of operation is not common for most of the user code, this change means that $q promises that utilze $evalAsync queue to guarantee asynchronicity of promise apis will now also resolve outside of a $digest, which turned out to be a big pain point for some developers. The implementation ensures that we don't do more work than needed and that we coalese as much work as possible into a single $digest. The use of $browser instead of setTimeout ensures that we can mock out and control the scheduling of "auto-flush", which should in theory allow all of the existing code and tests to work without negative side-effects. Closes #3539 Closes #2438
- Loading branch information
Showing
3 changed files
with
70 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6b91aa0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering @IgorMinar why you never created a digestAsync? Why does it only run on rootScope and not an individual scope?
6b91aa0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what a
$digestAsync
would be about. You can call$digest
whenever you want (e.g. async 😃). And you can run$digest
on a specific scope (if you know what you are doing).6b91aa0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the problem I am having is that I am not always in an angular context, like for instance, my HTTP calls are not using $http but some other data service, so whenever we get data we need to call $digest on the scope to update it. However, we have lots and lots and lots of directives (with isolated scopes) so sometimes we are double digesting - so ideally we have some mechanism to handle that like evalAsync does. We don't want to trigger a $rootScope.$digest because that is terrible for performance.
6b91aa0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. How about
$applyAsync()
then ? 😃6b91aa0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to run a $rootScope.$digest - ideally I would like to just run $scope.$digest and have all the nice stuff that evalAsync has in terms of phase/digest resolution
6b91aa0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For context I am working on a MASSIVE angular app, like .. MASSIVE, so we have a lot of watchers, a lot of directives, etc - so a $rootScope.$digest can be really expensive hence why trying to localize things to $scope.$digest();
6b91aa0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, basically you need a debounced/throttled
$scope.$digest
or an$applyAsync
that only runs$digest
on the local scope (not on$rootScope
). It should be fairly easy to implement (although not as straight-forwarded). Quick and hacky exampleConsidering this is a corner case (massive app doing stuff outside of the Angular context), I don't think we are too keen on adding that to core, because running
$digest
on a specific scope might have unexpected effects (e.g. not propagate changes to all bindings of the app or propagate changes unexpectedly), so we wouldn't want to encourage that.But that's just my opinion 😃
You could try opening a feature request issue and see what other people think.
6b91aa0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I totally think its specific to us, its a result of a lot of bad practices in our data (i know i know), but more than willing to share my code its essentially just evalAsync swapping out $rootScope.$digest() with $scope.$digest().
6b91aa0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like I said, I don't think it's a good fit for core (but maybe other have different opinions).
If you think it might be useful for more people, feel free to submit a PR or open a feature request to kick off some discussion 😃