Angular 7 rxjs BehaviorSubject 发射重复值
Angular 7 rxjs BehavioralSubject emiting repeated values
我还在学习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);
}
}
这里是改变值的组件
保存-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()中调用
创建或-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 错误,但无法弄清楚原因,谢谢。
可能 create-or-edit.component.ts
组件被多次创建和销毁。作为一般规则,在 ngonDestroy()
钩子中取消订阅总是安全的,以避免内存泄漏。
选项 1
您可以尝试在 ngDestroy()
挂钩中取消订阅。尝试以下
创建或-edit.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
挂钩中跟踪所有订阅和取消订阅可能会变得困难。您可以使用 解决方案来解决它。
设置以下共享函数:
// From
// 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() {
}
我还在学习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);
}
}
这里是改变值的组件
保存-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()中调用
创建或-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 错误,但无法弄清楚原因,谢谢。
可能 create-or-edit.component.ts
组件被多次创建和销毁。作为一般规则,在 ngonDestroy()
钩子中取消订阅总是安全的,以避免内存泄漏。
选项 1
您可以尝试在 ngDestroy()
挂钩中取消订阅。尝试以下
创建或-edit.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
挂钩中跟踪所有订阅和取消订阅可能会变得困难。您可以使用
设置以下共享函数:
// From
// 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() {
}