angular - Angular - 从 observable 的 observable 中获取 observables 数组
问题描述
我必须递归地列出observable
一个数组中生成的所有内容,以便稍后执行所有这些。
对于更多上下文,该对象currentLesson
有一个活动列表。但一个activity
可以是另一个lesson
与另一个活动作为孩子。在使用它之前,我必须(深度)加载所有活动。这就是我尝试使用递归函数的原因。
这是我的代码,但在构建结束时出现错误。我理解错误,但我不知道为什么data
是 anObservable<Observable<DataEntity>>
而不是 an 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.
解决方案
在这一行:
const data = this.getLessonById(activity.id)
.flatMap(subLesson => recursivelyGetActivityObservales(subLesson));
该函数recursivelyGetActivityObservales(subLesson)
返回一个数组,而不是 Observable。FlatMap/mergeMap 操作符需要返回一个 observable才能正常工作。
我不知道您将如何处理最终的 observables 数组,但如果您无论如何都要合并它,一个快速的解决方案是使用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 正确的解决方案只是返回 type 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);
}
解释:
An是一种数据结构,它通过调度程序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>
希望这可以帮助!
推荐阅读
- python - 我的主要过滤代码有什么问题?它不会返回正确的列表
- c++ - 我可以将参数类型分支到 C++17 中的参数包吗?
- python - Keras 值错误中的自定义损失函数
- javascript - 如何在 Vuejs 中的变量中传递方法名称
- maven-3 - 无法让 maven-assembly-plugin 打包测试
- jquery - jQuery 函数仅在我手动将窗口大小调整为移动设备而不是刷新时才有效
- java - 如何将项目输入资源放在 JAR 之外,如 Lib 文件夹
- python - TypeError 输出似乎倒退
- google-apps-script - Google 表格 - 用于将表格导出为仅包含值和格式的 xls 的按钮 - 不是公式
- rust - 如何从更高级别的特征绑定特征返回关联类型?