【发布时间】:2020-08-31 21:25:22
【问题描述】:
我正在使用 switchMap 和 combineLatest 将多个可观察对象加入到一个全局 joined$ 可观察对象中
这是组件 TS 文件:
export class ProgressComponent implements OnInit{
user: User;
joined$: Observable<any>;
constructor(
protected tasksService: TasksService,
protected courseService: CoursesService,
protected fieldService: FieldsService,
protected sessionService: SessionsService,
protected applicationService: ApplicationForSessionsService,
protected TaskdatesService: SessionTaskDatesService,
protected router: Router,
private userStore: UserStore)
{}
ngOnInit(): void {
this.user = this.userStore.getUser();
this.joined$ = this.applicationService.list(1, 10, undefined, this.user.id)
.pipe(
switchMap(applications => {
const courseSessionIds = uniq(applications.map(application => application.courseSessionId))
return combineLatest(
of(applications),
combineLatest(
courseSessionIds.map(courseSessionId => this.sessionService.get(courseSessionId).pipe(
switchMap(session => {
const courseId = session.courseId
return combineLatest(
of(session),
combineLatest(
this.courseService.get(courseId).pipe(
switchMap(course => {
const fieldId = course.fieldId
return combineLatest(
of(course),
combineLatest(
this.fieldService.get(fieldId).pipe(
map (field => field)
)
)
)
}),
map(([course, field]) => {
return {...course, field: field.find(f => f.id == course.fieldId)}
})
)
),
)
}),
map(([session, course]) => {
return {
...session,
course: course.find(c => c.id === session.courseId)
}
}),
switchMap( session => {
const sessionId = session.id;
return combineLatest(
of(session),
combineLatest(
this.TaskdatesService.getBySessionId(sessionId).pipe(
switchMap(dates => {
const taskDatesIds = uniq(dates.map(dt => dt.taskId));
return combineLatest(
of(dates),
combineLatest(
taskDatesIds.map(taskDateId => this.tasksService.get(taskDateId).pipe(
map(task => task)
))
)
)
}),
map(([dates, task]) => {
return dates.map(date => {
return {...date, task: task.find(t => t.id === date.taskId)}
})
})
)
)
)
}),
map(([session, dates]) => {
return {
...session,
dates: dates.map(date => date.find(d => d.sessionId === session.id))
}
})
))
)
)
}),
map(([applications, session]) => {
return applications.map(app => {
return {
...app,
session: session.find(s => s.id === app.courseSessionId)
}
})
})
);
}
}
这里是 HTML 模板文件
<ng-container *ngIf="joined$ | async; else loading; let joined">
<div *ngFor="let application of joined">
<div class="current-application">
<nb-card>
<nb-card-header>
<h4>{{application.session.course.name}}</h4>
<small><i>{{application.session.course.field.name}}</i></small>
</nb-card-header>
<nb-card-body>
<p><b>id: </b>{{application.id}}</p>
<p><b>applicationDate: </b>{{application.applicationDate}}</p>
<p><b>acceptedDate: </b>{{application.acceptedDate}}</p>
<hr>
<p><b>session Id: </b>{{application.session.id}}</p>
<p><b>session capacity: </b>{{application.session.capacity}}</p>
<p><b>session startDate: </b>{{application.session.startDate}}</p>
<p><b>session endDate: </b>{{application.session.endDate}}</p>
<hr>
<p><b>Course Id: </b>{{application.session.course.id}}</p>
<p><b>Course Id: </b>{{application.session.course.id}}</p>
</nb-card-body>
</nb-card>
</div>
</div>
</ng-container>
<ng-template #loading>
<p>Loding ...</p>
</ng-template>
编辑:调试后发现日期数组为空时会出现错误,所以解决方法是对日期数组的长度进行测试。问题是当我尝试创建条件时出现以下错误
'(dates: SessionTaskDate[]) => void' 类型的参数不能分配给'(value: SessionTaskDate[], index: number) => ObservableInput' 类型的参数。 类型“void”不可分配给类型“ObservableInput”。
在以下情况下触发:
switchMap(dates =>{
if(dates.length > 0){
dates.map(date => this.augmentDateWithTask(date))
}
})
【问题讨论】:
-
这代码太多了。乍一看:我认为你不应该在 combinelatest 中使用 switchmap(在 combineLates 之后使用它,并且当你的会话值已经可用时,你不必执行 of(session) ,仅举几个问题
-
这段代码非常复杂,难以理解。我建议把它分成小块。如果您的模板总是卡在加载中,那是因为
joined$从未发出值。当使用combineLatest时,它不会发出任何值,直到它的所有源 observables 都发出,所以这可能是你的问题。 -
您不需要使用
of和combineLatest。它们都是生成 observable 的函数。combineLatest在你有 2 个或更多源 observables 时使用。在您的情况下,您似乎只有一个来源,applicationService.list()。所以看起来你根本不需要combineLatest。 -
我关注了这个tutorial我只需要内部加入这些实体。
标签: angular typescript rxjs switchmap combinelatest