源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

浅谈Angular 中何时取消订阅

  • 时间:2021-02-24 16:02 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:浅谈Angular 中何时取消订阅
你可能知道当你订阅 Observable 对象或设置事件监听时,在某个时间点,你需要执行取消订阅操作,进而释放操作系统的内存。否则,你的应用程序可能会出现内存泄露。 接下来让我们看一下,需要在 ngOnDestroy 生命周期钩子中,手动执行取消订阅操作的一些常见场景。 [b]手动释放资源场景[/b] 表单
export class TestComponent {

 ngOnInit() {
  this.form = new FormGroup({...});
  // 监听表单值的变化
  this.valueChanges = this.form.valueChanges.subscribe(console.log);
  // 监听表单状态的变化              
  this.statusChanges = this.form.statusChanges.subscribe(console.log);
 }

 ngOnDestroy() {
  this.valueChanges.unsubscribe();
  this.statusChanges.unsubscribe();
 }
}
以上方案也适用于其它的表单控件。 路由
export class TestComponent {
 constructor(private route: ActivatedRoute, private router: Router) { }

 ngOnInit() {
  this.route.params.subscribe(console.log);
  this.route.queryParams.subscribe(console.log);
  this.route.fragment.subscribe(console.log);
  this.route.data.subscribe(console.log);
  this.route.url.subscribe(console.log);
  
  this.router.events.subscribe(console.log);
 }

 ngOnDestroy() {
  // 手动执行取消订阅的操作
 }
}

Renderer 服务
export class TestComponent {
 constructor(
  private renderer: Renderer2, 
  private element : ElementRef) { }

 ngOnInit() {
  this.click = this.renderer
    .listen(this.element.nativeElement, "click", handler);
 }

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

Infinite Observables 当你使用 interval() 或 fromEvent() 操作符时,你创建的是一个无限的 Observable 对象。这样的话,当我们不再需要使用它们的时候,就需要取消订阅,手动释放资源。
export class TestComponent {
 constructor(private element : ElementRef) { }

 interval: Subscription;
 click: Subscription;

 ngOnInit() {
  this.interval = Observable.interval(1000).subscribe(console.log);
  this.click = Observable.fromEvent(this.element.nativeElement, 'click')
              .subscribe(console.log);
 }

 ngOnDestroy() {
  this.interval.unsubscribe();
  this.click.unsubscribe();
 }
}
Redux Store
export class TestComponent {

 constructor(private store: Store) { }

 todos: Subscription;

 ngOnInit() {
   /**
   * select(key : string) {
   *  return this.map(state => state[key]).distinctUntilChanged();
   * }
   */
   this.todos = this.store.select('todos').subscribe(console.log); 
 }

 ngOnDestroy() {
  this.todos.unsubscribe();
 }
}
[b]无需手动释放资源场景 [/b] [b]AsyncPipe[/b]
@Component({
 selector: 'test',
 template: `<todos [todos]="todos$ | async"></todos>`
})
export class TestComponent {
 constructor(private store: Store) { }
 
 ngOnInit() {
   this.todos$ = this.store.select('todos');
 }
}
当组件销毁时,async 管道会自动执行取消订阅操作,进而避免内存泄露的风险。 [url=https://github.com/angular/angular/blob/master/packages/common/src/pipes/async_pipe.ts#L80]Angular AsyncPipe[/url] 源码片段
@Pipe({name: 'async', pure: false})
export class AsyncPipe implements OnDestroy, PipeTransform {
 // ...
 constructor(private _ref: ChangeDetectorRef) {}

 ngOnDestroy(): void {
  if (this._subscription) {
   this._dispose();
  }
 }
}
@HostListener
export class TestDirective {
 @HostListener('click')
 onClick() {
  ....
 }
}
需要注意的是,如果使用 @HostListener 装饰器,添加事件监听时,我们无法手动取消订阅。如果需要手动移除事件监听的话,可以使用以下的方式:
// subscribe
this.handler = this.renderer.listen('document', "click", event =>{...});

// unsubscribe
this.handler();
[b]Finite Observable[/b] 当你使用 HTTP 服务或 timer Observable 对象时,你也不需要手动执行取消订阅操作。
export class TestComponent {
 constructor(private http: Http) { }

 ngOnInit() {
  // 表示1s后发出值,然后就结束了
  Observable.timer(1000).subscribe(console.log);
  this.http.get('http://api.com').subscribe(console.log);
 }
}
[url=http://cn.rx.js.org/class/es6/Observable.js~Observable.html#static-method-timer]timer 操作符[/url] 操作符签名
[url=https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87]RxJS: Don't Unsubscribe [/url]这篇文章中了解与 Subject 相关更多信息。 具体示例如下:
export class TestComponent {
 constructor(private store: Store) { }

 private componetDestroyed: Subject = new Subject();
 todos: Subscription;
 posts: Subscription;

 ngOnInit() {
   this.todos = this.store.select('todos')
           .takeUntil(this.componetDestroyed).subscribe(console.log); 
           
   this.posts = this.store.select('posts')
           .takeUntil(this.componetDestroyed).subscribe(console.log); 
 }

 ngOnDestroy() {
  this.componetDestroyed.next();
  this.componetDestroyed.unsubscribe();
 }
}
[url=http://cn.rx.js.org/class/es6/Observable.js~Observable.html#instance-method-takeUntil]takeUntil 操作符[/url] 操作符签名
public takeUntil(notifier: Observable): Observable<T>
操作符作用 发出源 Observable 发出的值,直到 notifier Observable 发出值。 操作符示例
var interval = Rx.Observable.interval(1000);
var clicks = Rx.Observable.fromEvent(document, 'click');
var result = interval.takeUntil(clicks);

result.subscribe(x => console.log(x));
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程素材网。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部