我必须在一个数组中递归列出所有生成的observable
,以便稍后执行所有这些操作。
有关更多上下文,对象currentLesson
具有活动列表。但是一个activity
可以是另一个lesson
,并具有其他作为孩子的活动。使用前,我必须(深入)加载所有活动。这就是为什么我要使用递归函数。
这是我的代码,但是在构建结束时出现错误。我理解错误,但是我不知道为什么data
是Observable<Observable<DataEntity>>
而不是Observable<DataEntity>[]
,而且我也不知道该怎么做。
const recursivelyGetActivityObservales = (currentLesson: DataEntity): Observable<DataEntity>[] => {
const obsList: Observable<DataEntity>[] = [];
const activities: any[] = currentLesson.get('reference');
for (const activity of activities) {
if (activity['type'] === 'lesson') {
const data = this.getLessonById(activity.id).flatMap(subLesson => recursivelyGetActivityObservales(subLesson));
obsList.push(...data);
} else {
const loadedActivity = this.activitiesService.getActivityEntity(+activity.id);
if (loadedActivity) {
obsList.push(from([loadedActivity]));
} else {
obsList.push(this.activitiesService.loadActivitiesFromId(activity.id));
}
}
}
return obsList;
}
ERROR in src/app/@modules/activities/core/lessons/lessons.service.ts(321,37): error TS2461: Type 'Observable<Observable<DataEntity>>' is not an array type.
答案 0 :(得分:0)
在这一行:
const data = this.getLessonById(activity.id)
.flatMap(subLesson => recursivelyGetActivityObservales(subLesson));
函数recursivelyGetActivityObservales(subLesson)
返回的是数组,而不是Observable。 FlatMap / mergeMap操作员需要返回可观察的才能正常工作。
我不知道您将如何处理最终的可观察值数组,但是无论如何如果要进行合并,一种快速的解决方案是使用merge()
运算符。示例:
const lessons = (activity) => [
rxjs.from([1, 2, 3, 4]),
rxjs.from([1, 2, 3, 4]),
rxjs.from([1, 2, 3, 4]),
rxjs.from([1, 2, 3, 4])
]
const activity = rxjs.of('activity1');
const toSub = activity.pipe(rxjs.operators.mergeMap((activity) => rxjs.merge(...lessons(activity))))
toSub.subscribe(console.log)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.js"></script>
在您的代码中:
const data: Observable<DataEntity> = this.getLessonById(activity.id)
.flatMap(subLesson => merge(...recursivelyGetActivityObservales(subLesson)));
obsList.push(data);
首选解决方案:
说,IMO正确的解决方案将仅返回类型Observable<DataEntity>
,因为它还表示多个DataEntity对象。在这种用例中,没有理由要有一系列可观察对象。
为此,我只返回合并列表。 示例:
const recursivelyGetActivityObservales = (currentLesson: DataEntity): Observable<DataEntity> => {
const obsList: Observable<DataEntity>[] = [];
const activities: any[] = currentLesson.get('reference');
for (const activity of activities) {
if (activity['type'] === 'lesson') {
const data = this.getLessonById(activity.id).flatMap(subLesson => recursivelyGetActivityObservales(subLesson));
obsList.push(data);
} else {
const loadedActivity = this.activitiesService.getActivityEntity(+activity.id);
if (loadedActivity) {
obsList.push(from([loadedActivity]));
} else {
obsList.push(this.activitiesService.loadActivitiesFromId(activity.id));
}
}
}
return merge(...obsList);
}
外植体:
Observable<DataEntity>
是一种数据结构,它通过调度程序发出DataEntities(0、1或许多)。实际上是DataEntities的容器(如数组)。
以以下示例为例,其中两个数据结构等于相同的输出结果:
const lessonObsArray = [ // Observable<DataEntity>[]
rxjs.of(1),
rxjs.of(2),
rxjs.of(3),
rxjs.of(4),
]
const lessonObs = rxjs.merge( // Observable<DataEntity>
rxjs.of(1),
rxjs.of(2),
rxjs.of(3),
rxjs.of(4)
);
lessonObsArray.forEach(obs => obs.subscribe(console.log))
console.log('--------')
lessonObs.subscribe(console.log)
// They emit the same!!! (a collection of numbers in this case)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.js"></script>
希望这会有所帮助!