Skip to content

Commit 436301f

Browse files
authored
refactor(material/table): remove use of zone onStable for style scheduling (#28782)
* refactor(material/table): remove use of zone onStable for style scheduling Roll forward with fix for column resizer This reverts commit b01f682. * test: fix tests
1 parent 00fe374 commit 436301f

File tree

6 files changed

+77
-87
lines changed

6 files changed

+77
-87
lines changed

src/cdk-experimental/table-scroll-container/table-scroll-container.spec.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {CollectionViewer, DataSource} from '@angular/cdk/collections';
22
import {Component, Type, ViewChild} from '@angular/core';
3-
import {ComponentFixture, fakeAsync, flushMicrotasks, TestBed} from '@angular/core/testing';
3+
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
44
import {BehaviorSubject, combineLatest} from 'rxjs';
55
import {map} from 'rxjs/operators';
66
import {CdkTable, CdkTableModule} from '@angular/cdk/table';
@@ -48,10 +48,10 @@ describe('CdkTableScrollContainer', () => {
4848
dataRows = getRows(tableElement);
4949
});
5050

51-
it('sets scrollbar track margin for sticky headers', fakeAsync(() => {
51+
it('sets scrollbar track margin for sticky headers', waitForAsync(async () => {
5252
component.stickyHeaders = ['header-1', 'header-3'];
5353
fixture.detectChanges();
54-
flushMicrotasks();
54+
await new Promise(r => setTimeout(r));
5555

5656
if (platform.FIREFOX) {
5757
// ::-webkit-scrollbar-track is not recognized by Firefox.
@@ -66,18 +66,18 @@ describe('CdkTableScrollContainer', () => {
6666

6767
component.stickyHeaders = [];
6868
fixture.detectChanges();
69-
flushMicrotasks();
69+
await new Promise(r => setTimeout(r));
7070

7171
expect(scrollerStyle.getPropertyValue('margin-top')).toBe('0px');
7272
expect(scrollerStyle.getPropertyValue('margin-right')).toBe('0px');
7373
expect(scrollerStyle.getPropertyValue('margin-bottom')).toBe('0px');
7474
expect(scrollerStyle.getPropertyValue('margin-left')).toBe('0px');
7575
}));
7676

77-
it('sets scrollbar track margin for sticky footers', fakeAsync(() => {
77+
it('sets scrollbar track margin for sticky footers', waitForAsync(async () => {
7878
component.stickyFooters = ['footer-1', 'footer-3'];
7979
fixture.detectChanges();
80-
flushMicrotasks();
80+
await new Promise(r => setTimeout(r));
8181

8282
if (platform.FIREFOX) {
8383
// ::-webkit-scrollbar-track is not recognized by Firefox.
@@ -92,18 +92,18 @@ describe('CdkTableScrollContainer', () => {
9292

9393
component.stickyFooters = [];
9494
fixture.detectChanges();
95-
flushMicrotasks();
95+
await new Promise(r => setTimeout(r));
9696

9797
expect(scrollerStyle.getPropertyValue('margin-top')).toBe('0px');
9898
expect(scrollerStyle.getPropertyValue('margin-right')).toBe('0px');
9999
expect(scrollerStyle.getPropertyValue('margin-bottom')).toBe('0px');
100100
expect(scrollerStyle.getPropertyValue('margin-left')).toBe('0px');
101101
}));
102102

103-
it('sets scrollbar track margin for sticky start columns', fakeAsync(() => {
103+
it('sets scrollbar track margin for sticky start columns', waitForAsync(async () => {
104104
component.stickyStartColumns = ['column-1', 'column-3'];
105105
fixture.detectChanges();
106-
flushMicrotasks();
106+
await new Promise(r => setTimeout(r));
107107

108108
if (platform.FIREFOX) {
109109
// ::-webkit-scrollbar-track is not recognized by Firefox.
@@ -120,18 +120,18 @@ describe('CdkTableScrollContainer', () => {
120120

121121
component.stickyStartColumns = [];
122122
fixture.detectChanges();
123-
flushMicrotasks();
123+
await new Promise(r => setTimeout(r));
124124

125125
expect(scrollerStyle.getPropertyValue('margin-top')).toBe('0px');
126126
expect(scrollerStyle.getPropertyValue('margin-right')).toBe('0px');
127127
expect(scrollerStyle.getPropertyValue('margin-bottom')).toBe('0px');
128128
expect(scrollerStyle.getPropertyValue('margin-left')).toBe('0px');
129129
}));
130130

131-
it('sets scrollbar track margin for sticky end columns', fakeAsync(() => {
131+
it('sets scrollbar track margin for sticky end columns', waitForAsync(async () => {
132132
component.stickyEndColumns = ['column-4', 'column-6'];
133133
fixture.detectChanges();
134-
flushMicrotasks();
134+
await new Promise(r => setTimeout(r));
135135

136136
if (platform.FIREFOX) {
137137
// ::-webkit-scrollbar-track is not recognized by Firefox.
@@ -148,21 +148,21 @@ describe('CdkTableScrollContainer', () => {
148148

149149
component.stickyEndColumns = [];
150150
fixture.detectChanges();
151-
flushMicrotasks();
151+
await new Promise(r => setTimeout(r));
152152

153153
expect(scrollerStyle.getPropertyValue('margin-top')).toBe('0px');
154154
expect(scrollerStyle.getPropertyValue('margin-right')).toBe('0px');
155155
expect(scrollerStyle.getPropertyValue('margin-bottom')).toBe('0px');
156156
expect(scrollerStyle.getPropertyValue('margin-left')).toBe('0px');
157157
}));
158158

159-
it('sets scrollbar track margin for a combination of sticky rows and columns', fakeAsync(() => {
159+
it('sets scrollbar track margin for a combination of sticky rows and columns', waitForAsync(async () => {
160160
component.stickyHeaders = ['header-1'];
161161
component.stickyFooters = ['footer-3'];
162162
component.stickyStartColumns = ['column-1'];
163163
component.stickyEndColumns = ['column-6'];
164164
fixture.detectChanges();
165-
flushMicrotasks();
165+
await new Promise(r => setTimeout(r));
166166

167167
if (platform.FIREFOX) {
168168
// ::-webkit-scrollbar-track is not recognized by Firefox.
@@ -184,7 +184,7 @@ describe('CdkTableScrollContainer', () => {
184184
component.stickyStartColumns = [];
185185
component.stickyEndColumns = [];
186186
fixture.detectChanges();
187-
flushMicrotasks();
187+
await new Promise(r => setTimeout(r));
188188

189189
expect(scrollerStyle.getPropertyValue('margin-top')).toBe('0px');
190190
expect(scrollerStyle.getPropertyValue('margin-right')).toBe('0px');

src/cdk/table/coalesced-style-scheduler.ts

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {Injectable, NgZone, OnDestroy, InjectionToken} from '@angular/core';
10-
import {from, Subject} from 'rxjs';
11-
import {take, takeUntil} from 'rxjs/operators';
9+
import {Injectable, InjectionToken, NgZone, inject} from '@angular/core';
1210

1311
/**
1412
* @docs-private
@@ -31,11 +29,11 @@ export const _COALESCED_STYLE_SCHEDULER = new InjectionToken<_CoalescedStyleSche
3129
* @docs-private
3230
*/
3331
@Injectable()
34-
export class _CoalescedStyleScheduler implements OnDestroy {
32+
export class _CoalescedStyleScheduler {
3533
private _currentSchedule: _Schedule | null = null;
36-
private readonly _destroyed = new Subject<void>();
34+
private _ngZone = inject(NgZone);
3735

38-
constructor(private readonly _ngZone: NgZone) {}
36+
constructor(_unusedNgZone?: NgZone) {}
3937

4038
/**
4139
* Schedules the specified task to run at the end of the current VM turn.
@@ -56,22 +54,19 @@ export class _CoalescedStyleScheduler implements OnDestroy {
5654
this._currentSchedule!.endTasks.push(task);
5755
}
5856

59-
/** Prevent any further tasks from running. */
60-
ngOnDestroy() {
61-
this._destroyed.next();
62-
this._destroyed.complete();
63-
}
64-
6557
private _createScheduleIfNeeded() {
6658
if (this._currentSchedule) {
6759
return;
6860
}
6961

7062
this._currentSchedule = new _Schedule();
7163

72-
this._getScheduleObservable()
73-
.pipe(takeUntil(this._destroyed))
74-
.subscribe(() => {
64+
this._ngZone.runOutsideAngular(() =>
65+
// TODO(mmalerba): Scheduling this using something that runs less frequently
66+
// (e.g. requestAnimationFrame, setTimeout, etc.) causes noticeable jank with the column
67+
// resizer. We should audit the usages of schedule / scheduleEnd in that component and see
68+
// if we can refactor it so that we don't need to flush the tasks quite so frequently.
69+
queueMicrotask(() => {
7570
while (this._currentSchedule!.tasks.length || this._currentSchedule!.endTasks.length) {
7671
const schedule = this._currentSchedule!;
7772

@@ -88,14 +83,7 @@ export class _CoalescedStyleScheduler implements OnDestroy {
8883
}
8984

9085
this._currentSchedule = null;
91-
});
92-
}
93-
94-
private _getScheduleObservable() {
95-
// Use onStable when in the context of an ongoing change detection cycle so that we
96-
// do not accidentally trigger additional cycles.
97-
return this._ngZone.isStable
98-
? from(Promise.resolve(undefined))
99-
: this._ngZone.onStable.pipe(take(1));
86+
}),
87+
);
10088
}
10189
}

0 commit comments

Comments
 (0)