首页 > 解决方案 > NgRx 和 RxJS:依赖状态选择器

问题描述

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

 @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) 中的方法。组件中的LoadData()方法PGrid依赖于 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 的工作方式以及由于它们是异步的,因此一个函数可能不会在另一个函数之前返回值。

问题:1 为什么this.Data= selectedProcess.Data;设置this.Data为 undefined 即使 selectedProcess.Data有值

问题 2:我看过,flatMapswitchMap由于我是 RxJS 和 NgRx 的新手,我对如何利用它们感到困惑。有小费吗?

PS 在类似的说明中,我在我的 中分别订阅了 2 个切片ngOnInit(),这是首选方式还是应该将它们结合起来?

标签: angularrxjsngrxngrx-storeswitchmap

解决方案


一切都是流。

每个可观察的流都应该用 $ 命名。

避免使用订阅直到结束。

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

tap可用于副作用和日志记录,不会影响流。这是“我不知道我在做什么操作员”。我自由地使用它。

伪代码

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}`)
);

堆栈闪电战


推荐阅读