摘要:弄懂本篇文章,首先請(qǐng)看SNS項(xiàng)目筆記<四>--RX簡(jiǎn)要用法
在正常使用RX做監(jiān)聽的時(shí),時(shí)不時(shí)有些頁(yè)面需要重復(fù)點(diǎn)擊進(jìn)入,這樣在進(jìn)入該頁(yè)面的時(shí)候,會(huì)產(chǎn)生多次觸發(fā)subscribe方法,這個(gè)時(shí)候往往會(huì)出現(xiàn)多次賦值或者多次提交操作,即浪費(fèi)資源,也讓某些功能直接成為了Bug。于是博主就尋找了一天的源碼與探討了方法,特此記錄下來(lái)。
1、優(yōu)化封裝provider
在查找出現(xiàn)這樣的原因的時(shí)候,博主首先認(rèn)為是單例問(wèn)題,這里先貼出原來(lái)封裝好的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的一個(gè)Subject對(duì)象,這樣可能造成多次回調(diào)問(wèn)題,于是為了保險(xiǎn)起見,我重新整理了自定義單例的代碼:
//自定義單例類
export class MySubject extends Subject<any>{
public static readonly instance:MySubject = new MySubject()
private constructor(){
super()
}
}
這樣完成了單例對(duì)象的建立,本以為問(wèn)題得以解決,殊不知還是沒(méi)有解決重復(fù)問(wèn)題,于是開始翻閱源碼
2、RXjs部分源代碼

從subject源碼上我們難以看出問(wèn)題,其中有complete()和unsubscribe()供以使用,但是我試了下竟然將所有的監(jiān)聽移除了,這里可以看出并沒(méi)有寫complete()與unsubscribe()的使用情況于是繼續(xù)深入尋找js源碼:


說(shuō)明: "this.isStopped" 處理該subject對(duì)象是否繼續(xù)處理事件監(jiān)聽,"this,obervers" 存儲(chǔ)監(jiān)聽回調(diào)的對(duì)象Array,顯然在這兩個(gè)方法一個(gè)將數(shù)組置空,一個(gè)將數(shù)組直接賦值為null,并且isStopped狀態(tài)直接為true。這樣整個(gè)subscribe系統(tǒng)處于癱瘓狀態(tài),需要重新另起Subject對(duì)象來(lái)完成新的監(jiān)聽動(dòng)態(tài)。
3、重寫方法
掌握好其原理后,就好重寫方法來(lái)完成我們的需求,這里我們先整理下思路:
1、需要時(shí)刻保持subject活躍
2、需要在頁(yè)面pop過(guò)后進(jìn)行解綁其監(jiān)聽以達(dá)到不重復(fù)情況
3、注意的是在返回pop頁(yè)面的時(shí)候的監(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()
}
//解除最后一個(gè)綁定的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)了