我有一个可以在构造函数中订阅多个状态片的组件。
@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的工作方式所致,并且由于它们是异步的,因此一个函数可能不会在另一个函数之前返回值。
Que:1为什么this.Data= selectedProcess.Data;
设置this.Data
为undefined,即使selectedProcess.Data
有值
问题2:我看过flatMap
和switchMap
,但是由于我是RxJS和NgRx的新手,所以我对如何利用它们感到困惑。有提示吗?
P.S类似地,我在ngOnInit()
中分别订购了2个切片,这是首选方法还是应该将它们组合在一起?
答案 0 :(得分:1)
一切都是流。
每个可观察的流都应以$命名。
避免使用订阅直到结束。
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}`)
);