最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - angular Location.onUrlChange how to unsubscribe properly - Stack Overflow

programmeradmin4浏览0评论

Angular's Location service has a method onUrlChange that registers url events that popstate or hashchange don't, and I need that for a part of my project.

  /**
   * Registers a URL change listener. Use to catch updates performed by the Angular
   * framework that are not detectible through "popstate" or "hashchange" events.
   *
   * @param fn The change handler function, which take a URL and a location history state.
   */
  onUrlChange(fn: (url: string, state: unknown) => void) {
    this._urlChangeListeners.push(fn);
    this.subscribe(v => { this._notifyUrlChangeListeners(v.url, v.state); });
  }

Other than usually, there's no subscription returned, so we can't unsubscribe on destroy. The listener is still intact after navigating away from the route that needs to listen to those events.

My ugly hack for the moment is to filter Locations private _urlChangeListeners onDestroy, but that relies on String(fn) !== '(change) => this.urlFileHandler(change)' and clearly isn't a nice way.

Is there any other possibility to remove that listener from the listeners?

Angular's Location service has a method onUrlChange that registers url events that popstate or hashchange don't, and I need that for a part of my project.

  /**
   * Registers a URL change listener. Use to catch updates performed by the Angular
   * framework that are not detectible through "popstate" or "hashchange" events.
   *
   * @param fn The change handler function, which take a URL and a location history state.
   */
  onUrlChange(fn: (url: string, state: unknown) => void) {
    this._urlChangeListeners.push(fn);
    this.subscribe(v => { this._notifyUrlChangeListeners(v.url, v.state); });
  }

Other than usually, there's no subscription returned, so we can't unsubscribe on destroy. The listener is still intact after navigating away from the route that needs to listen to those events.

My ugly hack for the moment is to filter Locations private _urlChangeListeners onDestroy, but that relies on String(fn) !== '(change) => this.urlFileHandler(change)' and clearly isn't a nice way.

Is there any other possibility to remove that listener from the listeners?

Share Improve this question asked Jan 22, 2020 at 19:15 baaobaao 73.4k18 gold badges150 silver badges207 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 5

Not really an answer to the question but I decided to subscribe to it once and use an observable. For example:

  import { Location } from '@angular/mon';

  export class MyService {
    public urlChanged = new Subject();

    constructor(private location: Location) {
      // This is a shared service so the code only gets called once
      location.onUrlChange((url, state) => {
        this.urlChanged.next({ url, state });
      });
    }
 }

Then subscribe to it in the normal way, for example:

  private sub;

  ngOnInit() {
    this.sub = this.myService.urlChanged.subscribe(e => {
      //Do stuff
    });
  }

  ngOnDestroy() {
    this.sub.unsubscribe();
  }

To properly unsubscribe the callback, the onUrlChange method returns a VoidFunction that, on execution, will unregister the callback function.

const unregister = location.onUrlChange((url, state) => { ... });

// To unregister callback
unregister();

https://angular.io/api/mon/Location#onurlchange

You can use

ngOnDestroy() {
 this.location.ngOnDestroy();
}

Ps.: Location is injected at your constructor (private location: Location).

Since I only use one event suscription, I used this when I need to remove it:

(this.location as any)._urlChangeListeners = [];
发布评论

评论列表(0)

  1. 暂无评论