Angular RxJS:使用merge动态添加和删除Observable
我正在尝试构建一个可插拔的Angular RxJS:使用merge动态添加和删除Observable,angular,typescript,rxjs,rxjs6,Angular,Typescript,Rxjs,Rxjs6,我正在尝试构建一个可插拔的ProgressService 服务应该跟踪当前加载的“东西”数量。并且有一个isLoading()方法,该方法返回一个可观察的,以指示是否有任何东西正在加载 我的第一个解决方案非常简单,使用了一个新的行为子对象(0),然后每个加载提供程序只调用ProgressService.increase()和ProgressService.decrease()。这很有效。但如果可能的话,现在我想做更多的反应 然后我遇到了merge,当所有加载提供程序在开始时都是已知的时,它可以
ProgressService
服务应该跟踪当前加载的“东西”数量。并且有一个isLoading()
方法,该方法返回一个可观察的
,以指示是否有任何东西正在加载
我的第一个解决方案非常简单,使用了一个新的行为子对象(0)
,然后每个加载提供程序只调用ProgressService.increase()
和ProgressService.decrease()
。这很有效。但如果可能的话,现在我想做更多的反应
然后我遇到了
merge
,当所有加载提供程序在开始时都是已知的时,它可以正常工作:
this.progress=merge(…progressProviders).pipe(
扫描((acc,curr)=>acc+(curr?1:-1),0)
);
当任何加载提供程序发出true
或false
时,这只会增加/减少progress
值
但我还需要某种注册/注销功能。这基本上应该在合并链中添加一个新的可观察链
(或将其删除)
新的ProgressService
应如下所示:
类进程服务{
进度:Observable=EMPTY;//加载时值>0
addLoadingProvider(lp:可观察){
//当lp发出true时,增加this.progress
//当lp发出false时,减少此值。进度
//很好:如果lp的第一个发出值为false,则忽略
}
removeLoadingProvider(lp:可见){
//停止听lp
//清理:如果lp上次发出为真,则减少此进度
}
isLoading():可观察{
返回此.progress.pipe(
映射(val=>val!==0)
);
}
}
如果我们从addLoadingProvider
返回Subscription
,并使用Subscription.unsubscripte()
取消注册,则可能根本不需要removeLoadingProvider
方法(?)
希望有人能告诉我如何根据需要合并和取消合并其他观测值。根据您的解释,我可以理解以下内容[如果我的理解不正确,请纠正我]-
您希望收集发出布尔值的各种观察值,并希望以这种方式跟踪,如果其中任何一个至少有一个“true”
,则您的最终观察值应发出true,否则最终观察值应返回“false”
尽管你的行为主体方法是一种被动的方法。我建议采取以下办法:;让我知道这在你的场景中是否有意义-
方法1-
enum ListAction {
Added,
Removed,
Empty,
Undefined
}
export class ProgressService {
constructor() { }
progress: Observable<number> = EMPTY; // value > 0 when something is loading
obsListChanged: BehaviorSubject<ListAction> = new BehaviorSubject<any>(ListAction.Undefined);
obsList: Array<Observable<boolean>> = [];
addLoadingProvider(lp: Observable<boolean>) {
// increment this.progress, when lp emits true
// decrease this.progress, when lp emits false
// nice to have: ignore if lp's first emitted value is false
this.obsList.push(lp);
this.obsListChanged.next(ListAction.Added);
}
removeLoadingProvider(lp: Observable<boolean>) {
// stop listening to lp
// clean up: decrease this.progress, if lp last emitted true
this.obsList = this.obsList.filter(i => i !== lp);
this.obsListChanged.next(ListAction.Removed);
}
isLoading(): Observable<boolean> {
// return this.progress.pipe(
// map(val => val !== 0)
// );
return this.obsListChanged.pipe(
switchMap(() => {
return combineLatest(this.obsList);
}),
map(v => {
return v.some(loading => loading);
})
);
}
}
export class ProgressService {
constructor() { }
progress: Observable<number> = EMPTY; // value > 0 when something is loading
obsList$: BehaviorSubject<Array<Observable<boolean>>> = new BehaviorSubject<Array<Observable<boolean>>>([]);
addLoadingProvider(lp: Observable<boolean>) {
// increment this.progress, when lp emits true
// decrease this.progress, when lp emits false
// nice to have: ignore if lp's first emitted value is false
this.obsList$.next([...this.obsList$.getValue(), lp]);
}
removeLoadingProvider(lp: Observable<boolean>) {
// stop listening to lp
// clean up: decrease this.progress, if lp last emitted true
const removed = this.obsList$.getValue().filter(i => i !== lp);
this.obsList$.next(removed);
}
isLoading(): Observable<boolean> {
// return this.progress.pipe(
// map(val => val !== 0)
// );
return this.obsList$.pipe(
switchMap(obs => {
return combineLatest(obs);
}),
map(v => {
return v.some(loading => loading);
})
);
}
}
枚举列表操作{
补充,
远离的,
空的,,
未定义
}
出口级服务{
构造函数(){}
进度:Observable=EMPTY;//加载时值>0
obsListChanged:BehaviorSubject=新的BehaviorSubject(ListAction.Undefined);
obsList:Array=[];
addLoadingProvider(lp:可观察){
//当lp发出true时,增加this.progress
//当lp发出false时,减少此值。进度
//很好:如果lp的第一个发出值为false,则忽略
此.obsList.push(lp);
this.obsListChanged.next(ListAction.Added);
}
removeLoadingProvider(lp:可见){
//停止听lp
//清理:如果lp上次发出为真,则减少此进度
this.obsList=this.obsList.filter(i=>i!==lp);
this.obsListChanged.next(ListAction.Removed);
}
isLoading():可观察{
//返回此.progress.pipe(
//映射(val=>val!==0)
// );
返回此.obsListChanged.pipe(
开关映射(()=>{
返回CombineTest(此.obsList);
}),
地图(v=>{
返回v.some(加载=>加载);
})
);
}
}
我已经定义了一个ListAction可观察,如果您想按照ListAction执行特定的工作,那么您可以按照逻辑在rxjs操作符中执行相同的操作
方法2[方法1的改进版本]
enum ListAction {
Added,
Removed,
Empty,
Undefined
}
export class ProgressService {
constructor() { }
progress: Observable<number> = EMPTY; // value > 0 when something is loading
obsListChanged: BehaviorSubject<ListAction> = new BehaviorSubject<any>(ListAction.Undefined);
obsList: Array<Observable<boolean>> = [];
addLoadingProvider(lp: Observable<boolean>) {
// increment this.progress, when lp emits true
// decrease this.progress, when lp emits false
// nice to have: ignore if lp's first emitted value is false
this.obsList.push(lp);
this.obsListChanged.next(ListAction.Added);
}
removeLoadingProvider(lp: Observable<boolean>) {
// stop listening to lp
// clean up: decrease this.progress, if lp last emitted true
this.obsList = this.obsList.filter(i => i !== lp);
this.obsListChanged.next(ListAction.Removed);
}
isLoading(): Observable<boolean> {
// return this.progress.pipe(
// map(val => val !== 0)
// );
return this.obsListChanged.pipe(
switchMap(() => {
return combineLatest(this.obsList);
}),
map(v => {
return v.some(loading => loading);
})
);
}
}
export class ProgressService {
constructor() { }
progress: Observable<number> = EMPTY; // value > 0 when something is loading
obsList$: BehaviorSubject<Array<Observable<boolean>>> = new BehaviorSubject<Array<Observable<boolean>>>([]);
addLoadingProvider(lp: Observable<boolean>) {
// increment this.progress, when lp emits true
// decrease this.progress, when lp emits false
// nice to have: ignore if lp's first emitted value is false
this.obsList$.next([...this.obsList$.getValue(), lp]);
}
removeLoadingProvider(lp: Observable<boolean>) {
// stop listening to lp
// clean up: decrease this.progress, if lp last emitted true
const removed = this.obsList$.getValue().filter(i => i !== lp);
this.obsList$.next(removed);
}
isLoading(): Observable<boolean> {
// return this.progress.pipe(
// map(val => val !== 0)
// );
return this.obsList$.pipe(
switchMap(obs => {
return combineLatest(obs);
}),
map(v => {
return v.some(loading => loading);
})
);
}
}
导出类ProgressService{
构造函数(){}
进度:Observable=EMPTY;//加载时值>0
obsList$:BehaviorSubject=新的BehaviorSubject([]);
addLoadingProvider(lp:可观察){
//当lp发出true时,增加this.progress
//当lp发出false时,减少此值。进度
//很好:如果lp的第一个发出值为false,则忽略
this.obsList$.next([…this.obsList$.getValue(),lp]);
}
removeLoadingProvider(lp:可见){
//停止听lp
//清理:如果lp上次发出为真,则减少此进度
const removed=this.obsList$.getValue().filter(i=>i!==lp);
此.obsList$.next(已删除);
}
isLoading():可观察{
//返回此.progress.pipe(
//映射(val=>val!==0)
// );
返回此.obsList$.pipe(
开关映射(obs=>{
返回组合测试(obs);
}),
地图(v=>{
返回v.some(加载=>加载);
})
);
}
}