摘要:弄懂本篇文章浸船,首先請看SNS項目筆記<四>--RX簡要用法
在正常使用RX做監(jiān)聽的時褪储,時不時有些頁面需要重復(fù)點擊進(jìn)入蟀架,這樣在進(jìn)入該頁面的時候瓣赂,會產(chǎn)生多次觸發(fā)subscribe方法榆骚,這個時候往往會出現(xiàn)多次賦值或者多次提交操作,即浪費資源煌集,也讓某些功能直接成為了Bug妓肢。于是博主就尋找了一天的源碼與探討了方法,特此記錄下來苫纤。
1碉钠、優(yōu)化封裝provider
在查找出現(xiàn)這樣的原因的時候,博主首先認(rèn)為是單例問題方面,這里先貼出原來封裝好的provider:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class RxBus{
private param: any;
private subject: Subject<any> = new Subject()
setListener(param: any): void {
this.param= param;
this.subject.next(param);
}
bus(): Observable<any> {
return this.subject.asObservable();
}
}
這里subject直接為new的一個Subject對象放钦,這樣可能造成多次回調(diào)問題,于是為了保險起見恭金,我重新整理了自定義單例的代碼:
//自定義單例類
export class MySubject extends Subject<any>{
public static readonly instance:MySubject = new MySubject()
private constructor(){
super()
}
}
這樣完成了單例對象的建立操禀,本以為問題得以解決,殊不知還是沒有解決重復(fù)問題横腿,于是開始翻閱源碼
2颓屑、RXjs部分源代碼
從subject源碼上我們難以看出問題,其中有complete()和unsubscribe()供以使用耿焊,但是我試了下竟然將所有的監(jiān)聽移除了揪惦,這里可以看出并沒有寫complete()與unsubscribe()的使用情況于是繼續(xù)深入尋找js源碼:
說明: "this.isStopped" 處理該subject對象是否繼續(xù)處理事件監(jiān)聽,"this,obervers" 存儲監(jiān)聽回調(diào)的對象Array罗侯,顯然在這兩個方法一個將數(shù)組置空器腋,一個將數(shù)組直接賦值為null,并且isStopped狀態(tài)直接為true钩杰。這樣整個subscribe系統(tǒng)處于癱瘓狀態(tài)纫塌,需要重新另起Subject對象來完成新的監(jiān)聽動態(tài)。
3讲弄、重寫方法
掌握好其原理后措左,就好重寫方法來完成我們的需求,這里我們先整理下思路:
1避除、需要時刻保持subject活躍
2怎披、需要在頁面pop過后進(jìn)行解綁其監(jiān)聽以達(dá)到不重復(fù)情況
3、注意的是在返回pop頁面的時候的監(jiān)聽不可取消
于是重構(gòu)代碼:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class RxBus{
private param: any;
private subject: MySubject<any> = MySubject.instance
setListener(param: any): void {
this.param= param;
this.subject.next(param);
}
bus(): Observable<any> {
return this.subject.asObservable();
}
//公開方法
complete(){
this.subject.finish()
}
}
//自定義單例類
export class MySubject extends Subject<any>{
public static readonly instance:MySubject = new MySubject()
private constructor(){
super()
}
//解除最后一個綁定的observe
finish(){
if (this.closed) {
return
}
let len = this.observers.length;
let observers = this.observers.splice(len-1,1);
}
}
在page里面調(diào)用生命周期方法:
ionViewDidLeave(){
this.rxbus.compelete()
}
這樣便完成了只有一次回調(diào)了