-
Notifications
You must be signed in to change notification settings - Fork 6.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(scrolling): viewport ruler events being run inside zone #15814
Conversation
3bf795d
to
c716c72
Compare
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.
LGTM
c716c72
to
1fbd878
Compare
Bumping to a P2 since we got a report about this potentially affecting perf. |
src/cdk/scrolling/viewport-ruler.ts
Outdated
this._change = _platform.isBrowser ? | ||
merge(fromEvent(window, 'resize'), fromEvent(window, 'orientationchange')) : | ||
observableOf(); | ||
|
||
// Note that we need to do the subscription inside `runOutsideAngular` | ||
// since subscribing is what causes the event listener to be added. | ||
this._invalidateCache = this.change().subscribe(() => this._updateViewportSize()); | ||
if (_platform.isBrowser) { | ||
// Note that bind the events ourselves, rather than going through something like RxJS's | ||
// `fromEvent` so that we can ensure that they're bound outside of the NgZone. | ||
window.addEventListener('resize', this._changeListener); | ||
window.addEventListener('orientationchange', this._changeListener); | ||
} | ||
|
||
// We don't need to keep track of the subscription, | ||
// because we complete the `change` stream on destroy. | ||
this.change().subscribe(() => this._updateViewportSize()); |
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.
Here I would change a little bit the piece code, I would do something like:
this._change = _platform.isBrowser ?
merge(fromEvent(window, 'resize'), fromEvent(window, 'orientationchange'))
.pipe(runOutsideZone(ngZone)) :
observableOf();
where:
/** Runs this observable outside the zone */
function runOutsideZone<T>(zone: NgZone): any {
return (source: Observable<T>): Observable<T> => {
return new Observable(observer => {
return zone.runOutsideAngular<Subscription>(() => source.subscribe(observer));
});
};
}
Seems cleaner and more understandable IMO, also is less code.
Is there any blocking issue that causes this MR to not be merged? Just for know. I also miss the 'zone re-entering' of the subscriptions that need it. For example the select component & the paginated-tab-header. Here I have a proposal MR (same of this one, I actually copy the tests, thanks @crisbeto) where I do this 'zone re-enterings': |
1fbd878
to
4990078
Compare
Fixes the `resize` and `orientationchange` events of the `ViewportRuler` being run inside the `NgZone`, if the subscription comes from inside the zone. Fixes angular#18471.
4990078
to
0745739
Compare
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Fixes the
resize
andorientationchange
events of theViewportRuler
being run inside theNgZone
, if the subscription comes from inside the zone.Fixes #18471.