SNS项目笔记<七>--深入探究RXjs
摘要:弄懂本篇文章,首先请看SNS项目笔记<四>--RX简要用法
在正常使用RX做监听的时,时不时有些页面需要重复点击进入,这样在进入该页面的时候,会产生多次触发subscribe方法,这个时候往往会出现多次赋值或者多次提交操作,即浪费资源,也让某些功能直接成为了Bug。于是博主就寻找了一天的源码与探讨了方法,特此记录下来。
1、优化封装provider
在查找出现这样的原因的时候,博主首先认为是单例问题,这里先贴出原来封装好的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对象,这样可能造成多次回调问题,于是为了保险起见,我重新整理了自定义单例的代码:
//自定义单例类
export class MySubject extends Subject<any>{
public static readonly instance:MySubject = new MySubject()
private constructor(){
super()
}
}
这样完成了单例对象的建立,本以为问题得以解决,殊不知还是没有解决重复问题,于是开始翻阅源码
2、RXjs部分源代码
Subject源代码.png从subject源码上我们难以看出问题,其中有complete()和unsubscribe()供以使用,但是我试了下竟然将所有的监听移除了,这里可以看出并没有写complete()与unsubscribe()的使用情况于是继续深入寻找js源码:
JS源码--complete方法.png JS源码--unsubscribe方法.png说明: "this.isStopped" 处理该subject对象是否继续处理事件监听,"this,obervers" 存储监听回调的对象Array,显然在这两个方法一个将数组置空,一个将数组直接赋值为null,并且isStopped状态直接为true。这样整个subscribe系统处于瘫痪状态,需要重新另起Subject对象来完成新的监听动态。
3、重写方法
掌握好其原理后,就好重写方法来完成我们的需求,这里我们先整理下思路:
1、需要时刻保持subject活跃
2、需要在页面pop过后进行解绑其监听以达到不重复情况
3、注意的是在返回pop页面的时候的监听不可取消
于是重构代码:
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里面调用生命周期方法:
ionViewDidLeave(){
this.rxbus.compelete()
}
这样便完成了只有一次回调了