Subject和observable同样能够被订阅,可是它们在被屡次订阅的时候表现是不同的。vue
observable在被屡次订阅时,每一次的订阅都是独立的,也是重头开始的订阅,订阅之间不会相互干涉。以下所示git
const test = interval(1000);
test.subscribe(res => console.log(res))
setTimeout(() => {
test.subscribe(res => console.log(res))
}, 1000);
// 0
// 1
// 0
// 2
// 1
// 3
// 2
....
复制代码
可是在实际状况中,有的时候咱们不但愿他们是独立的,在不少须要共享触发的状况下,咱们会但愿他们在订阅的时候,不会从头返回,而是全部订阅都返回相同的触发,而这个就是Subject的做用。github
理解一个东西最好的办法就是手写一个,Subject的实现能够理解为用一个中介来获取全部observers,而后在触发时同时执行。vuex
const subject = {
observers: [],
subscribe: function(observer) {
this.observers.push(observer)
},
next: function(value) {
this.observers.forEach(o => o.next(value))
},
error: function(error){
this.observers.forEach(o => o.error(error))
},
complete: function() {
this.observers.forEach(o => o.complete())
}
}
const c = interval(1000);
test.subscribe(subject.subscribe(res => cosnole.log('a:' + res)))
setTimeout(() => {
test.subscribe(subject.subscribe(res => cosnole.log('b:' + res)))
}, 1000);
// a:0
// a:1
// b:1
// a:2
// b:2
// a:3
// b:3
// a:4
...
复制代码
手写的这个Subject和实际的实现有一些小差异,不过将Subject的关键点都覆盖到了。 Subject具备两个特色:bash
依据这两个特性,Subject常常被用在一些须要主动触发的场合,还有一些不一样组件之间共享变化的状况。学习
例如一个网页有一个国际化需求,能够设置多种语言类型,在选择了语言类型以后,全部模块的语言都会发生变化,若是项目很大组件繁多,用简单的组件间通信就会很是麻烦,熟悉vue的同窗通常会用vuex来解决这种问题,而Rxjs就能够很简单的作到。在咱们只须要公共的服务中new一个Subject对象,在设置语言变化的时候触发Subject.next(language),而后在须要的作出改变的模块中监听这个Subject的变化输出便可。以angular代码为例:ui
// common service
languageChange$ = new Subject();
changeLanguage(language){
setLang(language);
this.languageChange$.next(language);
}
复制代码
// other components
constructor(
private _srv: CommonService
) {
this._srv.languageChange$.subscribe(language => {
this.setLanguage(language)
})
}
setLanguage() {
...
}
复制代码
这种须要实现一处变化多处相应的状况,Subject是一把利器。this
有一个经常使用到的需求,在一个组件,经常会有多个observable存在监听各类事件的发生,在关闭这个组件时,咱们须要中止掉全部的observable,这个也能够用Subject来统一监听,统一关闭。以angular代码为例:spa
private _unsubscribe$ = new Subject<void>();
someObservable.pipe(
takeUntil(this._unsubscribe$),
someOperators...
).subscribe(callback)
ngOnDestroy() {
this._unsubscribe$.next();
this._unsubscribe$.complete();
}
复制代码
github上有一个项目封装了一个流程管理的库,用的就是rxjs里的subject。code
有兴趣的能够去学习这个库的源码实现,相信对RxJs的理解提升有很大帮助.