亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

淺談Angular 中何時取消訂閱

發布時間:2020-08-24 21:58:20 來源:腳本之家 閱讀:163 作者:semlinker 欄目:web開發

你可能知道當你訂閱 Observable 對象或設置事件監聽時,在某個時間點,你需要執行取消訂閱操作,進而釋放操作系統的內存。否則,你的應用程序可能會出現內存泄露。

接下來讓我們看一下,需要在 ngOnDestroy 生命周期鉤子中,手動執行取消訂閱操作的一些常見場景。

手動釋放資源場景

表單

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();
 }
}

無需手動釋放資源場景

AsyncPipe

@Component({
 selector: 'test',
 template: `<todos [todos]="todos$ | async"></todos>`
})
export class TestComponent {
 constructor(private store: Store) { }
 
 ngOnInit() {
   this.todos$ = this.store.select('todos');
 }
}

當組件銷毀時,async 管道會自動執行取消訂閱操作,進而避免內存泄露的風險。

Angular AsyncPipe 源碼片段

@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();

Finite Observable

當你使用 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);
 }
}

timer 操作符

操作符簽名

復制代碼 代碼如下:

public static timer(initialDelay: number | Date, period: number, scheduler: Scheduler): Observable

操作符作用

timer 返回一個發出無限自增數列的 Observable,具有一定的時間間隔,這個間隔由你來選擇。

操作符示例

// 每隔1秒發出自增的數字,3秒后開始發送
var numbers = Rx.Observable.timer(3000, 1000);
numbers.subscribe(x => console.log(x));

// 5秒后發出一個數字
var numbers = Rx.Observable.timer(5000);
numbers.subscribe(x => console.log(x));

最終建議

你應該盡可能少的調用 unsubscribe() 方法,你可以在RxJS: Don't Unsubscribe 這篇文章中了解與 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();
 }
}

takeUntil 操作符

操作符簽名

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));

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武隆县| 灵山县| 同江市| 宜黄县| 东安县| 敖汉旗| 高密市| 汨罗市| 宁化县| 静乐县| 花垣县| 南皮县| 焦作市| 垣曲县| 上饶市| 天津市| 嘉善县| 正阳县| 澎湖县| 延吉市| 北碚区| 阆中市| 桃江县| 灌云县| 奉节县| 花莲县| 保康县| 高州市| 宁都县| 上栗县| 仙游县| 津南区| 游戏| 宜兰县| 紫阳县| 商河县| 六枝特区| 喀喇沁旗| 依安县| 永仁县| 兴化市|