RxJs处于Angular状态时,我是否只需要完成在组件中创建的观测值?
基本上,我仍然不确定如何清理角度组件中的反应性代码。以下规则是否正确且充分 我的反应性组件规则:RxJs处于Angular状态时,我是否只需要完成在组件中创建的观测值?,angular,typescript,rxjs,Angular,Typescript,Rxjs,基本上,我仍然不确定如何清理角度组件中的反应性代码。以下规则是否正确且充分 我的反应性组件规则: 在手动x.subscribe()上: 如果使用x.takeUntil(…)或类似构造,则无需手动清理 如果在组件范围内调用x.complete(),则无需手动清理 else手册。按需取消订阅()或在Ngondestory()中取消订阅 在模板的可观察|异步上: 无需手动清理,且与onPush兼容 手动直接创建可观察的新主体() ngondstroy()中的manual.complete(
- 在手动x.subscribe()上:
- 如果使用x.takeUntil(…)或类似构造,则无需手动清理
- 如果在组件范围内调用x.complete(),则无需手动清理
- else手册。按需取消订阅()或在Ngondestory()中取消订阅
- 在模板的可观察|异步上:
- 无需手动清理,且与onPush兼容
- 手动直接创建可观察的新主体()
- ngondstroy()中的manual.complete()否则永远不会关闭
- 在使用其他可观察对象(如Observable.merge(…)手动创建时:
- 只要已清理订阅,就不需要手动清理
import { ChangeDetectionStrategy, Component, Input, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { DeliveryPointId } from 'app/bso';
import { BookmarkService } from 'app/general';
import { EAccess, EPermission, ReduxGetters, ReduxService } from 'app/redux';
import * as routing from 'app/routing';
import { BehaviorSubject, Observable } from 'app/rx';
@Component({
selector: 'app-last-opened-workitems-widget',
templateUrl: './last-opened-workitems-widget.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LastOpenedWorkitemsWidgetComponent implements OnDestroy {
private readonly showPartners$ = new BehaviorSubject(true);
private readonly showServices$ = new BehaviorSubject(true);
private readonly showTens$ = new BehaviorSubject(true);
private readonly showWorklist$ = new BehaviorSubject(true);
@Input() set showItems(val: boolean) { this.showWorklist$.next(!!val); }
@Input() set showPartners(val: boolean) { this.showPartners$.next(!!val); }
@Input() set showProcesses(val: boolean) { this.showServices$.next(!!val); }
@Input() set showTens(val: boolean) { this.showTens$.next(!!val); }
constructor(
private readonly redux: ReduxService,
private readonly bookmarks: BookmarkService,
private readonly router: Router,
) { }
canPartners$ = this.redux.watch(ReduxGetters.userAccess).map(access => access[EPermission.Partner] >= EAccess.Read);
canServices$ = this.redux.watch(ReduxGetters.userAccess).map(access => access[EPermission.Services] >= EAccess.Read);
canTens$ = this.redux.watch(ReduxGetters.userAccess).map(access => access[EPermission.Tens] >= EAccess.Read);
canWorklist$ = this.redux.watch(ReduxGetters.userAccess).map(access => access[EPermission.Worklist] >= EAccess.Read);
lastItems$ = this.bookmarks.onLastOpenedWorkitems.map(ii => [...ii].reverse());
lastPartners$ = this.bookmarks.onLastOpenedPartners.map(ii => [...ii].reverse());
lastProcesses$ = this.bookmarks.onLastOpenedProcesses.map(ii => [...ii].reverse());
lastTens$ = this.bookmarks.onLastOpenedTens.map(ii => [...ii].reverse());
hasContentPartners$ = Observable
.combineLatest(
this.showPartners$.distinctUntilChanged(),
this.canPartners$,
this.lastPartners$.map(ii => ii.length > 0))
.map(oks => oks.every(ii => ii));
hasContentServices$ = Observable
.combineLatest(
this.showServices$.distinctUntilChanged(),
this.canServices$,
this.lastProcesses$.map(ii => ii.length > 0))
.map(oks => oks.every(ii => ii));
hasContentTens$ = Observable
.combineLatest(
this.showTens$.distinctUntilChanged(),
this.canTens$,
this.lastTens$.map(ii => ii.length > 0))
.map(oks => oks.every(ii => ii));
hasContentWorklist$ = Observable
.combineLatest(
this.showWorklist$.distinctUntilChanged(),
this.canWorklist$,
this.lastItems$.map(ii => ii.length > 0))
.map(oks => oks.every(ii => ii));
hasContent$ = Observable
.combineLatest(this.hasContentPartners$, this.hasContentServices$, this.hasContentTens$, this.hasContentWorklist$)
.map(oks => oks.some(ii => ii));
ngOnDestroy() {
[this.showPartners$, this.showServices$, this.showTens$, this.showWorklist$].forEach(ii => ii.complete());
}
gotoPartner = (id: string) => routing.gotoPartnerItem(this.router, id);
gotoProcess = (id: number) => routing.gotoProcess(this.router, id);
gotoTensItem = (id: DeliveryPointId) => routing.gotoTensItem(this.router, id);
gotoWorkitem = (id: number) => routing.gotoWorkitem(this.router, id);
}
您需要取消订阅每个订阅,例如在
ngondstroy()
方法中
或者,您可以使用诸如takeUntil()
、take()
、first()
等运算符来“限制”可观察对象
上述规则也适用于CombineTest
不要担心由AsyncPipe
创建的订阅,因为AsyncPipe
本身负责取消订阅
关于这个主题的一个很好的读物是RxJS负责人Ben Lesh的。好的,我实际上刚刚测试了它。最后(…)加上所有中间观测值的日志记录,当组件被销毁时,它会被正确触发
因此,我声明上述规则正确且充分。Thx,但这基本上就是我上面总结的内容。订阅清理在这里不是我的问题,但要弄清楚是否以及何时需要手动完成观察对象本身(即调用complete()。