【问题标题】:Angular 7 rxjs BehavioralSubject emiting repeated valuesAngular 7 rxjs BehaviorSubject 发出重复值
【发布时间】: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 错误,但无法弄清楚原因,谢谢。

【问题讨论】:

  • 您如何将数据存储到状态中..?当您使用这些服务类方法来存储值时...?
  • 您可能面临内存泄漏问题,当您打开创建或编辑组件时,保存选项组件会被删除?

标签: angular rxjs observable 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://stackoverflow.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() {
}

【讨论】:

  • 如果他在多个组件中使用这个服务怎么样..?
  • 然后他需要在每个组件中取消订阅。我在答案中包含了另一种不那么乏味的方式。
猜你喜欢
  • 1970-01-01
  • 2018-08-31
  • 1970-01-01
  • 2017-02-02
  • 1970-01-01
  • 1970-01-01
  • 2021-08-11
  • 2018-11-07
  • 1970-01-01
相关资源
最近更新 更多