国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

淺談Angular 中何時取消訂閱

2019-11-19 14:52:56
字體:
來源:轉載
供稿:網友

你可能知道當你訂閱 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 裝飾器,添加事件監聽時,我們無法手動取消訂閱。如果需要手動移除事件監聽的話,可以使用以下的方式:

// subscribethis.handler = this.renderer.listen('document', "click", event =>{...});// unsubscribethis.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));

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 美姑县| 锡林郭勒盟| 温泉县| 中牟县| 长泰县| 肇源县| 阿拉善左旗| 新乡市| 紫阳县| 邯郸市| 湟源县| 通道| 洛扎县| 什邡市| 嘉定区| 仲巴县| 莱州市| 永宁县| 沅江市| 怀安县| 淄博市| 肥西县| 武清区| 乌兰察布市| 钦州市| 思茅市| 平塘县| 耒阳市| 德庆县| 五华县| 朔州市| 当雄县| 阿尔山市| 兴业县| 专栏| 会昌县| 禄丰县| 涿鹿县| 綦江县| 武冈市| 石柱|