我想在用户单击按钮时导出包含数据列表的文件。我有一个可观察的(user$),其中包含用户的身份。如果用户无权获取此数据,他们将被重定向到另一个页面。如果用户确实获得了授权,则从后端检索数据并将其导出到电子表格中(这部分并不重要,我知道该怎么做)。文件的标题取决于用户的身份。
我被困在:
onClick(){
this.user$.pipe(
tap((user: User) => {
if (!user.isAuthorised) {
this.router.navigate(["/someOtherPage"]);
}
}),
switchMap((user: User) => {
let myData$: Observable<Array<Data>> =
this.myDataService.getDataByUserName(user.name);
this.exportService.exportFile(myData$, user.name);
})
);
}
exportFile(Array, string) 方法需要导出数据作为输入,并且需要用户的名称来构成电子表格的标题。我如何以干净有效的方式组合所有这些可观察到的结果?
如果我对问题的理解正确的话,您需要使用以下服务调用中服务返回的数据来连接对某些异步服务的 3 个调用。
如果这个理解是正确的,那么我会进行如下操作
onClick(){
this.user$.pipe(
tap((user: User) => {
if (!user.isAuthorised) {
this.router.navigate(["/someOtherPage"]);
}
}),
// switchMap waits for the previous Observable to emit something
// and, as soon as it emits, pass the control to the following Observable
switchMap((user: User) =>
// here you may want to check if the user is authorized (consider
// that the tap operator used above is not stopping the stream
// and therefore you enter this function even if you navigate
// to another page - if the user is not authorized, then you
// end the entire stream returning EMPY, which is an Observable
// that does not do anything but completes immediately
if (!user.isAuthorised) {
return EMPTY
}
// the function passed to switchMap as parameter MUST return an Observable
// in this case probably you want to return the Observable that
// retrieves the data for the user from the back end
return this.myDataService.getDataByUserName(user.name).pipe(
// the point here is that, for the following Observable, you
// need both the data returned by getDataByUserName and the user
// returned by this.user$
// to do so you can pipe in a map operator like this
map(dataForUserFromBackEnd => {
return {user, dataForUserFromBackEnd }
})
}),
// now you need another switchMap to pass the control to the final
// Observable, the one returned by exportFile
switchMap(({user, dataForUserFromBackEnd }) => {
return this.exportService.exportFile(myData$, user.name);
})
);
}