我有一个如下组件,其中有一个按钮在单击时调用
select_property
。问题是我不确定在每次点击时重新分配 $livevisitors
之前是否需要以任何方式取消订阅,不确定组件模板中的 $livevisitors | async
是否对我有用。
export class LiveComponent{
livevisitors$: Observable<LiveVisitor[]>;
selected_property_id: number = 0;
constructor(
private store: Store<AppState>
) {
this.livevisitors$ = this.store.select(selectAllLiveVisitors);
}
select_property(id){
this.selected_property_id = id;
if (id == 0){
this.livevisitors$ = this.store.select(selectAllLiveVisitors);
} else {
this.livevisitors$ = this.store.select(selectLiveVisitorsByPropertyId, {property_id: id});
}
}
但是,如果您订阅组件中的可观察对象,则会引入潜在的内存泄漏:
export class LiveComponent{
livevisitors$: Observable<LiveVisitor[]>;
selected_property_id: number = 0;
constructor(
private store: Store<AppState>
) {
}
ngOnInit() {
//Potential memory leak
this.store.select(selectAllLiveVisitors).subscribe(() = > {...})
}
}
如果是这种情况,那么您需要在组件被销毁时取消订阅。一个优雅的解决方案是声明一个主题属性:
export class LiveComponent implements OnInit, OnDestroy {
destroyed$: Subject<void> = new Subject<void>();
livevisitors$: Observable<LiveVisitor[]>;
selected_property_id: number = 0;
constructor(
private store: Store<AppState>
) {
}
ngOnInit() {
// will unsubscribe when component is destroyed
this.store.select(selectAllLiveVisitors)
.pipe(takeUntil(this.destroyed$))
.subscribe(() = > {...})
}
ngOnDestroy() {
this.destroyed$.next();
this.destroyed$.complete();
}
}
当我们在OnInit方法中订阅时,可能存在潜在的内存泄漏。示例:
export class RegisterComponent extends BaseComponent implements OnInit {
loading = false;
constructor(private store: Store) {}
ngOnInit(): void {
this.store.select(fromAuth.selectAuthLoading)
.subscribe(loading => this.loading = loading);
}
}
当我们使用异步管道时,我们是安全的。示例:
HTML:
@if (recipe$ | async; as recipe) {
<div> {{recipe.name}} </div>
}
TS:
export class RecipeDetailComponent implements OnInit {
recipe$: Observable<Recipe | null> = this.store.select(fromRecipes.selectRecipeDetails);
constructor(private store: Store) {
}
ngOnInit(): void {
}
}
为了扩展 Or Shalmayev 评论,我们实际上可以扩展我们正在订阅的组件。
TS基础.组件:
@Injectable()
export class BaseComponent implements OnDestroy {
destroyed$: Subject<void> = new Subject<void>();
ngOnDestroy() {
this.destroyed$.next();
this.destroyed$.complete();
}
}
TS寄存器组件:
@Component({
selector: 'app-register',
standalone: true,
imports: [],
templateUrl: './register.component.html',
styleUrl: './register.component.scss'
})
export class RegisterComponent extends BaseComponent implements OnInit {
loading = false;
constructor(private store: Store) {
super();
}
ngOnInit(): void {
this.store.select(fromAuth.selectAuthLoading)
.pipe(takeUntil(this.destroyed$))
.subscribe(loading => this.loading = loading);
}
}
总结一下: 我更喜欢使用异步管道,但也可以扩展组件并使我们的组件干净。