Skip to content

Commit

Permalink
perf(core): avoid changes Observable creation on QueryList (angular#5…
Browse files Browse the repository at this point in the history
…3498)

The changes Observable (impl: EventEmitter) on the QueryList is initalized
lazy - it is created only if someone calls a geter to get a hand on its
instance. But the destroy method was calling this getter thus creating
a new Observable even if no one subscribed to it.

This commit changes the destroy logic to skip creation of an EventEmitter
if it wasn't initialized.

PR Close angular#53498
  • Loading branch information
pkozlowski-opensource authored and ChellappanRajan committed Jan 23, 2024
1 parent 1864477 commit 3fc73ce
Showing 1 changed file with 7 additions and 5 deletions.
12 changes: 7 additions & 5 deletions packages/core/src/linker/query_list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class QueryList<T> implements Iterable<T> {
public readonly dirty = true;
private _results: Array<T> = [];
private _changesDetected: boolean = false;
private _changes: EventEmitter<QueryList<T>>|null = null;
private _changes: EventEmitter<QueryList<T>>|undefined = undefined;

readonly length: number = 0;
readonly first: T = undefined!;
Expand All @@ -57,7 +57,7 @@ export class QueryList<T> implements Iterable<T> {
* Returns `Observable` of `QueryList` notifying the subscriber of changes.
*/
get changes(): Observable<any> {
return this._changes || (this._changes = new EventEmitter());
return this._changes ??= new EventEmitter();
}

/**
Expand Down Expand Up @@ -169,7 +169,7 @@ export class QueryList<T> implements Iterable<T> {
* Triggers a change event by emitting on the `changes` {@link EventEmitter}.
*/
notifyOnChanges(): void {
if (this._changes && (this._changesDetected || !this._emitDistinctChangesOnly))
if (this._changes !== undefined && (this._changesDetected || !this._emitDistinctChangesOnly))
this._changes.emit(this);
}

Expand All @@ -180,8 +180,10 @@ export class QueryList<T> implements Iterable<T> {

/** internal */
destroy(): void {
(this.changes as EventEmitter<any>).complete();
(this.changes as EventEmitter<any>).unsubscribe();
if (this._changes !== undefined) {
this._changes.complete();
this._changes.unsubscribe();
}
}

// The implementation of `Symbol.iterator` should be declared here, but this would cause
Expand Down

0 comments on commit 3fc73ce

Please sign in to comment.