我有两个带有嵌套订阅的函数。
期望的行为:
进行路由
foo(): void {
this.httpHandler.updateUser(userData).subscribe(
(successUserData) => this.uploadAvatar().subscribe(
(url) => this.route.navigate(url) //finish, some routing based on result url;
)
)
}
//returns an url or '' if skipped
uploadAvatar(): Observable<string> {
let subject = new Subject<string>();
if (!skipFileUpload) {
this.httpHandler.uploadImage(this.file).subscribe(
(successData) => {
this.httpHandler.verifySomething(successData.id).subscribe(
(verifiedData) =>
if (verifiedData)
subject.next(verifiedData.url)
)
}
)
} else {
subject.next('');
}
return subject.asObservable();
}问题:
如果文件未上载,则可观察到的文件不会解析。换句话说:subject.next('');不工作,而我的“”路由没有发生。
然而,如果上传发生了,那么所有的事情都会按预期工作。
整个过程是否可以简化或简化呢?
提前谢谢。
发布于 2021-09-06 05:07:17
您尚未编写错误处理程序:
uploadAvatar(): Observable<string> {
let subject = new Subject<string>();
if (!skipFileUpload) {
this.httpHandler.uploadImage(this.file).subscribe(
(successData) => {
this.httpHandler.verifySomething(successData.id).subscribe(
(verifiedData) =>
if (verifiedData)
subject.next(verifiedData.url)
)
},
// **** you had not handled the error case
(error) => { subject.next(); subject.complete(); }
);
} else {
subject.next('');
subject.complete(); // else it will ramin a hot obervable
}
return subject.asObservable();
}您可以使用'concatMap‘'catchError’管道‘跳过多次订阅。
发布于 2021-09-06 05:29:37
不需要嵌套多个订阅,您可以使用管道将其夷平。我根据您想要的行为修改了代码。
首先是更新用户数据。接下来,根据您发布的代码,如果我们跳过文件上传,如果不是,我们将调用upload Image调用。然后,如果上传图像调用成功,我们将调用verifySomething api调用。最后,当一切都成功时,我们从verifySomething url路由到url返回。
注意到:我添加了一个条件来检查响应参数是否有url属性,因为当我们跳过uploadImage api调用时,我们可能会得到一个没有url的响应。
updateProfile(): void {
this.httpHandler
.updateUser(userData)
.pipe(
mergeMap((e) => {
if (!skipFileUpload) {
return this.httpHandler.uploadImage(this.file).pipe(
mergeMap((successData) => {
this.httpHandler.verifySomething(successData.id);
})
);
} else {
return of(e);
}
}),
catchError((err) => {
console.error(err);
throw err;
})
)
.subscribe((res) => {
if (res && res.url) {
this.route.navigate(res.url);
}
});
}发布于 2021-09-06 06:47:48
您可以使用switchMap来解决这个问题。
foo(): void {
this.httpHandler.updateUser(userData).pipe(
switchMap(() => this.uploadAvatar())
).subscribe((url) => this.route.navigate(url))
}
//returns an url or '' if skipped
uploadAvatar(): Observable<string> {
let subject = new Subject<string>();
if (!skipFileUpload) {
const sub = this.httpHandler.uploadImage(this.file).pipe(
switchMap((successData) => this.httpHandler.verifySomething(successData.id))
tap((verifiedData) => subject.next(verifiedData ? verifiedData.url : ''))
catchError(e => { subject.next(''); return throwError(e) })
).subscribe();
} else {
subject.next('');
}
return subject.asObservable();
}在uploadAvatar__中,应该正确管理订阅。
如果只在updateAvatar中使用foo函数,则可以跳过额外的函数。
foo(): void {
this.httpHandler.updateUser(userData).pipe(
map(() => skipFileUpload ? throwError('') : this.httpHandler.uploadImage(this.file))
switchMap(obs => obs),
map(successData => (successData && successData.id) ? this.httpHandler.verifySomething(successData.id) : throwError('')),
switchMap(obs => obs),
map(verifiedData => verifiedData ? of(verifiedData) : throwError('')),
switchMap(obs => obs),
catchError(err => { this.route.navigate(url); return throwError(err); })
)
).subscribe((url) => this.route.navigate(url))
}https://stackoverflow.com/questions/69069226
复制相似问题