NgRx 和 RxJS:依赖状态选择器

NgRx and RxJS : Dependent State Selector

我有一个组件在构造函数中订阅了多个状态片段。

 @ViewChild(PComponent) PGrid: PComponent;

ngOnInit() {
    this.store.pipe(
          select(fromReports.getProcessState),
          takeWhile(() => this.componentActive))
          .subscribe(selectedProcess=> {
            if (selectedProcess) {
              this.Data= selectedProcess.Data;
  }
          });

  this.store.pipe(
          select(fromReports.getProcessAnalysis),
          takeWhile(() => this.componentActive))
          .subscribe(analysisData => {
            if (analysisData) {
              this.PGrid.LoadData(analysisData);
              }
          });
}

第一个订阅订阅对象数组,而第二个订阅调用另一个组件中的方法(@ViewChild(PComponent) PGrid)。 PGrid 组件中的 LoadData() 方法依赖于第一个订阅的 this.Data。

当我 运行 代码时,我得到了未定义的代码。数据虽然 selectedProcess.Data 有价值

this.store.pipe(
          select(fromReports.getProcessState),
          takeWhile(() => this.componentActive))
          .subscribe(selectedProcess=> {
            if (selectedProcess) {
              this.Data= selectedProcess.Data; //undefined

  }
          });

这意味着当订阅状态的第二个切片并调用 LoadData() 方法时,它会出错,因为 this.Data 未定义。

我相信这是由于 Observable 的工作方式所致,并且由于它们是异步的,所以一个函数可能不会 return 另一个函数之前的值。

问题:1 为什么 this.Data= selectedProcess.Data;this.Data 设置为未定义,即使 selectedProcess.Data 具有值

问题 2:我看过 flatMapswitchMap,但由于我是 RxJS 和 NgRx 的新手,所以我对如何利用它们感到困惑。有什么建议吗?

P.S 同样,我在我的 ngOnInit() 中分别订阅了 2 个切片,这是首选方式还是我应该合并它们?

万物皆流。

每个可观察流都应以 $.

命名

避免在最后使用订阅。

combineLatest 在每个 Observable 至少发出一个值之前不会发出初始值。

tap 可用于副作用和日志记录,不影响流。这是 "I don't know what I'm doing operator"。我大方地使用它。

伪代码

import { of, combineLatest } from "rxjs";
import { map, delay, tap, switchMap } from "rxjs/operators";

const DATA = "selectedProcessData";
const PROCESS_ANALYSIS = "analysis";

const service = {
  getData: () => {
    return of(DATA).pipe(delay(2000));
  },
  loadData: data => {
    return of(data).pipe(delay(2000));
  }
};
const store = {
  getProcessAnalysis: () => {
    return of(PROCESS_ANALYSIS).pipe(delay(2000));
  }
};

let getSelectedProcessData = null;
const getSelectedProcessData$ = service.getData().pipe(
  tap(data => console.log(`getSelectedProcessData::${data}`)),
  tap(data => (getSelectedProcessData = data))
); // mimick getting data from a service

const getAnalysisData$ = store.getProcessAnalysis(); // mimick selection of state

const loadAnalysisData$ = combineLatest(
  getSelectedProcessData$,
  getAnalysisData$
).pipe(
  tap(([getSelectedProcessData, getAnalysisData]) =>
    console.log(`combineLatest::${getSelectedProcessData}, ${getAnalysisData}`)
  ),
  map(([getSelectedProcessData, getAnalysisData]) => getAnalysisData),
  switchMap(getAnalysisData => service.loadData(getAnalysisData))
);

loadAnalysisData$.subscribe(loadedAnalysisData =>
  console.log(`loadedAnalysisData::${loadedAnalysisData}`)
);

Stackblitz