angular - 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:我看过,flatMap
但switchMap
由于我是 RxJS 和 NgRx 的新手,我对如何利用它们感到困惑。有小费吗?
PS 在类似的说明中,我在我的 中分别订阅了 2 个切片ngOnInit()
,这是首选方式还是应该将它们结合起来?
解决方案
一切都是流。
每个可观察的流都应该用 $ 命名。
避免使用订阅直到结束。
在每个 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}`)
);
堆栈闪电战
推荐阅读
- dataframe - 如何将 pyspark 数据框的列值转换为逗号分隔的字符串
- python - 更改包含工作日的日期时间格式?
- c - 如果我不设置'pthread_join',为什么线程会死
- python - 数据框左合并与不同列中的匹配键
- android - 除非在观察者方法中再次声明适配器,否则不会显示 recyclerview 中的项目
- laravel - Maatwebsite Excel - 如何命名多张工作表?
- ruby-on-rails-4 - Will_paginate,Ruby on Rails,条件
- c - 函数 yes_or_no 应该返回 1 或 0,并根据它结束或循环程序,但它永远循环
- node.js - 手动刷新或写入时,React 路由器 URL 不起作用。并获取 html 数据而不是 JSON 数据
- python - 我怎样才能用python杀死一个线程