fix(common): prevent duplicate URL change notifications (#37404)
Prevent duplicate notifications from being emitted when multiple URL change listeners are registered using Location#onUrlChange. PR Close #37404
This commit is contained in:
parent
eb6ba9ac80
commit
3569fdf451
|
@ -64,6 +64,7 @@ export class Location {
|
|||
_platformLocation: PlatformLocation;
|
||||
/** @internal */
|
||||
_urlChangeListeners: ((url: string, state: unknown) => void)[] = [];
|
||||
private _urlChangeSubscription?: SubscriptionLike;
|
||||
|
||||
constructor(platformStrategy: LocationStrategy, platformLocation: PlatformLocation) {
|
||||
this._platformStrategy = platformStrategy;
|
||||
|
@ -194,9 +195,12 @@ export class Location {
|
|||
*/
|
||||
onUrlChange(fn: (url: string, state: unknown) => void) {
|
||||
this._urlChangeListeners.push(fn);
|
||||
this.subscribe(v => {
|
||||
this._notifyUrlChangeListeners(v.url, v.state);
|
||||
});
|
||||
|
||||
if (!this._urlChangeSubscription) {
|
||||
this._urlChangeSubscription = this.subscribe(v => {
|
||||
this._notifyUrlChangeListeners(v.url, v.state);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import {CommonModule, Location, LocationStrategy, PathLocationStrategy, PlatformLocation} from '@angular/common';
|
||||
import {MockPlatformLocation} from '@angular/common/testing';
|
||||
import {MockLocationStrategy, MockPlatformLocation} from '@angular/common/testing';
|
||||
import {inject, TestBed} from '@angular/core/testing';
|
||||
|
||||
const baseUrl = '/base';
|
||||
|
@ -84,7 +84,7 @@ describe('Location Class', () => {
|
|||
TestBed.configureTestingModule({
|
||||
imports: [CommonModule],
|
||||
providers: [
|
||||
{provide: LocationStrategy, useClass: PathLocationStrategy},
|
||||
{provide: LocationStrategy, useClass: MockLocationStrategy},
|
||||
{
|
||||
provide: PlatformLocation,
|
||||
useFactory: () => {
|
||||
|
@ -113,5 +113,30 @@ describe('Location Class', () => {
|
|||
expect((location as any)._urlChangeListeners.length).toBe(1);
|
||||
expect((location as any)._urlChangeListeners[0]).toEqual(changeListener);
|
||||
}));
|
||||
|
||||
it('should only notify listeners once when multiple listeners are registered', () => {
|
||||
const location = TestBed.inject(Location);
|
||||
const locationStrategy = TestBed.inject(LocationStrategy) as MockLocationStrategy;
|
||||
let notificationCount = 0;
|
||||
|
||||
function incrementChangeListener(url: string, state: unknown) {
|
||||
notificationCount += 1;
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function noopChangeListener(url: string, state: unknown) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
location.onUrlChange(incrementChangeListener);
|
||||
location.onUrlChange(noopChangeListener);
|
||||
|
||||
expect(notificationCount).toBe(0);
|
||||
|
||||
locationStrategy.simulatePopState('/test');
|
||||
|
||||
expect(notificationCount).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue