冒泡 HTTP post 对组件的响应
Bubble up HTTP post response to component
如何让 UserCourseService
中 setUserCourses
的结果冒泡到 DashboardBodyHomeCourseModalComponent
?目前,result
returns null.
此外,我目前正在传递一个名为 courseSelectedOptions
的数组,它对我的 API 执行多个 HTTP 调用。在最后一个 API 调用结束时,我想冒泡一个 HTTP post 响应到我的组件。
UserCourseService
setUserCourses(userId: string, courseSelectedOptions: number[]): Promise<unknown | void> {
return this.firebaseService.generateToken().then((token: string) => {
this.logger.debug(`Token generated for setUserCourses: ${token}`);
return observableFrom(courseSelectedOptions)
.pipe(
concatMap((courseSelectedOption) =>
this.httpClient.post(
`${environment.apiBasePath}/userCourses`,
{
user_id: userId,
course_id: courseSelectedOption,
},
{ headers: { authorization: `Bearer ${token}` } }
)
)
)
.subscribe(
(response) => this.logger.debug(`setUserCourses response: ${JSON.stringify(response)}`),
(error) => this.logger.debug(`setUserCourses error: ${JSON.stringify(error)}`),
() => this.logger.debug('setUserCourses complete')
);
});
}
DashboardBodyHomeFacade
setUserCourses(userId: string, courseSelectedOptions: number[]): Promise<unknown | void> {
return this.userCourseService.setUserCourses(userId, courseSelectedOptions);
}
DashboardBodyHomeCourseModalComponent
this.dashboardBodyHomeFacade
.setUserCourses(this.user.id, this.courseSelectedOptions)
.then((result: unknown) => {
if (result) {
this.toastrService.success('Your courses have been selected.', 'Great!');
this.bsModalRef.hide();
} else {
this.toastrService.warning('Something has gone wrong. Please try again.', 'Oops!');
}
})
.catch(() => {
this.toastrService.warning('Something has gone wrong. Please try again.', 'Oops!');
});
这是混合 observables 和 promises 的经典案例。我建议您使用 RxJS from
函数将承诺转换为可观察对象。之后,您可以使用高阶映射运算符(此处为 switchMap
)映射到 HTTP 请求,从服务中 return 并在组件中订阅。
服务
setUserCourses(userId: string, courseSelectedOptions: number[]): Observable<any> { // <-- return the observable
return from(this.firebaseService.generateToken()).pipe(
switchMap(token => {
this.logger.debug(`Token generated for setUserCourses: ${token}`);
return this.httpClient.post(
`${environment.apiBasePath}/userCourses`,
{
user_id: userId,
course_id: courseSelectedOptions,
},
{ headers: { authorization: `Bearer ${token}` } }
)
}),
tap(
(response) => this.logger.debug(`setUserCourses response: ${JSON.stringify(response)}`),
(error) => this.logger.debug(`setUserCourses error: ${JSON.stringify(error)}`),
() => this.logger.debug('setUserCourses complete')
)
);
}
组件
this.dashboardBodyHomeFacade.setUserCourses(this.user.id, this.courseSelectedOptions).subscribe(
result => {
if (result) {
this.toastrService.success('Your courses have been selected.', 'Great!');
this.bsModalRef.hide();
} else {
this.toastrService.warning('Something has gone wrong. Please try again.', 'Oops!');
}
},
error => this.toastrService.warning('Something has gone wrong. Please try again.', 'Oops!')
);
更新:对 courseSelectedOptions
中每个项目的多个请求
您可以使用 RxJS forkJoin
函数和 Array#map
为 courseSelectedOptions
中的每个项目触发多个并行 HTTP 请求。尝试以下
setUserCourses(userId: string, courseSelectedOptions: number[]): Observable<any> { // <-- return the observable
return from(this.firebaseService.generateToken()).pipe(
switchMap(token => {
this.logger.debug(`Token generated for setUserCourses: ${token}`);
return forkJoin(courseSelectedOptions.map(courseSelectedOption => // <-- trigger parallel requests for each item in `courseSelectedOptions`
this.httpClient.post(
`${environment.apiBasePath}/userCourses`,
{
user_id: userId,
course_id: courseSelectedOption,
},
{ headers: { authorization: `Bearer ${token}` } }
)
))
}),
tap(
(response) => this.logger.debug(`setUserCourses response: ${JSON.stringify(response)}`),
(error) => this.logger.debug(`setUserCourses error: ${JSON.stringify(error)}`),
() => this.logger.debug('setUserCourses complete')
)
);
}
如何让 UserCourseService
中 setUserCourses
的结果冒泡到 DashboardBodyHomeCourseModalComponent
?目前,result
returns null.
此外,我目前正在传递一个名为 courseSelectedOptions
的数组,它对我的 API 执行多个 HTTP 调用。在最后一个 API 调用结束时,我想冒泡一个 HTTP post 响应到我的组件。
UserCourseService
setUserCourses(userId: string, courseSelectedOptions: number[]): Promise<unknown | void> {
return this.firebaseService.generateToken().then((token: string) => {
this.logger.debug(`Token generated for setUserCourses: ${token}`);
return observableFrom(courseSelectedOptions)
.pipe(
concatMap((courseSelectedOption) =>
this.httpClient.post(
`${environment.apiBasePath}/userCourses`,
{
user_id: userId,
course_id: courseSelectedOption,
},
{ headers: { authorization: `Bearer ${token}` } }
)
)
)
.subscribe(
(response) => this.logger.debug(`setUserCourses response: ${JSON.stringify(response)}`),
(error) => this.logger.debug(`setUserCourses error: ${JSON.stringify(error)}`),
() => this.logger.debug('setUserCourses complete')
);
});
}
DashboardBodyHomeFacade
setUserCourses(userId: string, courseSelectedOptions: number[]): Promise<unknown | void> {
return this.userCourseService.setUserCourses(userId, courseSelectedOptions);
}
DashboardBodyHomeCourseModalComponent
this.dashboardBodyHomeFacade
.setUserCourses(this.user.id, this.courseSelectedOptions)
.then((result: unknown) => {
if (result) {
this.toastrService.success('Your courses have been selected.', 'Great!');
this.bsModalRef.hide();
} else {
this.toastrService.warning('Something has gone wrong. Please try again.', 'Oops!');
}
})
.catch(() => {
this.toastrService.warning('Something has gone wrong. Please try again.', 'Oops!');
});
这是混合 observables 和 promises 的经典案例。我建议您使用 RxJS from
函数将承诺转换为可观察对象。之后,您可以使用高阶映射运算符(此处为 switchMap
)映射到 HTTP 请求,从服务中 return 并在组件中订阅。
服务
setUserCourses(userId: string, courseSelectedOptions: number[]): Observable<any> { // <-- return the observable
return from(this.firebaseService.generateToken()).pipe(
switchMap(token => {
this.logger.debug(`Token generated for setUserCourses: ${token}`);
return this.httpClient.post(
`${environment.apiBasePath}/userCourses`,
{
user_id: userId,
course_id: courseSelectedOptions,
},
{ headers: { authorization: `Bearer ${token}` } }
)
}),
tap(
(response) => this.logger.debug(`setUserCourses response: ${JSON.stringify(response)}`),
(error) => this.logger.debug(`setUserCourses error: ${JSON.stringify(error)}`),
() => this.logger.debug('setUserCourses complete')
)
);
}
组件
this.dashboardBodyHomeFacade.setUserCourses(this.user.id, this.courseSelectedOptions).subscribe(
result => {
if (result) {
this.toastrService.success('Your courses have been selected.', 'Great!');
this.bsModalRef.hide();
} else {
this.toastrService.warning('Something has gone wrong. Please try again.', 'Oops!');
}
},
error => this.toastrService.warning('Something has gone wrong. Please try again.', 'Oops!')
);
更新:对 courseSelectedOptions
中每个项目的多个请求
您可以使用 RxJS forkJoin
函数和 Array#map
为 courseSelectedOptions
中的每个项目触发多个并行 HTTP 请求。尝试以下
setUserCourses(userId: string, courseSelectedOptions: number[]): Observable<any> { // <-- return the observable
return from(this.firebaseService.generateToken()).pipe(
switchMap(token => {
this.logger.debug(`Token generated for setUserCourses: ${token}`);
return forkJoin(courseSelectedOptions.map(courseSelectedOption => // <-- trigger parallel requests for each item in `courseSelectedOptions`
this.httpClient.post(
`${environment.apiBasePath}/userCourses`,
{
user_id: userId,
course_id: courseSelectedOption,
},
{ headers: { authorization: `Bearer ${token}` } }
)
))
}),
tap(
(response) => this.logger.debug(`setUserCourses response: ${JSON.stringify(response)}`),
(error) => this.logger.debug(`setUserCourses error: ${JSON.stringify(error)}`),
() => this.logger.debug('setUserCourses complete')
)
);
}