Angular 7 rxjs BehaviorSubject 发出重复值
Posted
技术标签:
【中文标题】Angular 7 rxjs BehaviorSubject 发出重复值【英文标题】:Angular 7 rxjs BehavioralSubject emiting repeated values 【发布时间】:2020-09-07 23:22:44 【问题描述】:我还在学习rxjs,遇到了问题。
我有一个带有 BehavioralSubject 的服务,旨在保存单个值并在更改时将其发送给其他组件。其他组件将更改该值,以便它们在组件之间进行通信-我将它与一个组件一起使用,该组件在从订阅中接收特定值时执行 http 请求以保存文档(另一个组件负责更改该值)。一旦我启动应用程序,它就可以正常工作,但第二次它发出 2 次值,发送 2 个 http 请求,第 3 次发送 3 个,第 4 次发送 4 个,依此类推......
这是服务的代码
save.service.ts
export class SaveService
readonly state: BehaviorSubject<SAVE_STATE>;
constructor()
this.state = new BehaviorSubject(SAVE_STATE.IDLE);
public save()
this.state.next(SAVE_STATE.SAVE);
public reset()
this.state.next(SAVE_STATE.RESET);
public changed()
this.state.next(SAVE_STATE.CHANGED);
public idle()
this.state.next(SAVE_STATE.IDLE);
public loading()
this.state.next(SAVE_STATE.LOADING);
这里是改变值的组件
save-options.component.ts
private show: boolean;
private loading: boolean;
constructor(private saveService: SaveService)
ngOnInit()
this.show = false;
this.saveService.state.subscribe((state) =>
this.show = state === SAVE_STATE.IDLE ? false : true;
this.loading = state === SAVE_STATE.LOADING ? true : false;
);
saveAction()
this.saveService.save();
discardAction()
this.saveService.reset();
这是组件中接收值并发出请求的函数,该方法在 ngOnInit()
中调用create-or-edit.component.ts
private listenToSaveEvents()
this.saveService.state.subscribe((state) =>
console.log(state);
switch(state)
case SAVE_STATE.SAVE:
this.saveStore();
break;
case SAVE_STATE.RESET:
this.undo();
break;
default:
break;
);
后面的函数是增量执行多次的函数。日志的结果是: 第一次执行
0
3
4
3
第二次执行
0
3
4
3
0
3
(2)4
(2)3
我可能使用 BehaviorSubject 错误,但无法弄清楚原因,谢谢。
【问题讨论】:
您如何将数据存储到状态中..?当您使用这些服务类方法来存储值时...? 您可能面临内存泄漏问题,当您打开创建或编辑组件时,保存选项组件会被删除? 【参考方案1】:可能create-or-edit.component.ts
组件被创建和销毁多次。作为一般规则,在 ngonDestroy()
挂钩中取消订阅总是安全的,以避免内存泄漏。
选项 1
您可以尝试在 ngDestroy()
挂钩中取消订阅。试试下面的
创建或编辑.component.ts
stateSubscription: any;
private listenToSaveEvents()
this.stateSubscription = this.saveService.state.subscribe((state) =>
console.log(state);
switch(state)
case SAVE_STATE.SAVE:
this.saveStore();
break;
case SAVE_STATE.RESET:
this.undo();
break;
default:
break;
);
ngOnDestroy()
if (this.stateSubscription)
this.stateSubscription.unsubscribe();
选项 2
在ngOnDestroy
挂钩中跟踪所有订阅和取消订阅可能会变得很困难。您可以使用this 解决方案来解决它。
设置以下共享功能:
// From https://***.com/a/45709120/6513921
// Based on https://www.npmjs.com/package/ng2-rx-componentdestroyed
import OnDestroy from '@angular/core';
import ReplaySubject from 'rxjs';
export function componentDestroyed(component: OnDestroy)
const oldNgOnDestroy = component.ngOnDestroy;
const destroyed$ = new ReplaySubject<void>(1);
component.ngOnDestroy = () =>
oldNgOnDestroy.apply(component);
destroyed$.next(undefined);
destroyed$.complete();
;
return destroyed$.asObservable();
现在要做的就是在组件中实现ngOnDestroy
并将takeUntil(componentDestroyed(this))
添加到管道中。
import pipe from 'rxjs';
import takeUntil from 'rxjs/operators';
private listenToSaveEvents()
this.stateSubscription = this.saveService.state
.pipe(takeUntil(componentDestroyed(this))) // <-- pipe it in here
.subscribe((state) =>
console.log(state);
switch(state)
case SAVE_STATE.SAVE:
this.saveStore();
break;
case SAVE_STATE.RESET:
this.undo();
break;
default:
break;
);
ngOnDestroy()
【讨论】:
如果他在多个组件中使用这个服务怎么样..? 然后他需要在每个组件中取消订阅。我在答案中包含了另一种不那么乏味的方式。以上是关于Angular 7 rxjs BehaviorSubject 发出重复值的主要内容,如果未能解决你的问题,请参考以下文章
Angular 7 RxJs - HTTP 调用未在 ForkJoin 中完成
Angular 7 rxjs BehaviorSubject 发出重复值