首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Angular12 12/rxjs/typescript:可观察不完整(内部/嵌套订阅)

Angular12 12/rxjs/typescript:可观察不完整(内部/嵌套订阅)
EN

Stack Overflow用户
提问于 2021-09-06 04:45:46
回答 3查看 111关注 0票数 0

我有两个带有嵌套订阅的函数。

期望的行为:

  1. 更新用户数据
  2. 如果上一步成功更新用户图标
  3. 如果上一步成功或跳过/错误了->完成,只需使用返回的url

进行路由

代码语言:javascript
复制
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('');不工作,而我的“”路由没有发生。

然而,如果上传发生了,那么所有的事情都会按预期工作。

整个过程是否可以简化或简化呢?

提前谢谢。

EN

回答 3

Stack Overflow用户

发布于 2021-09-06 05:07:17

您尚未编写错误处理程序:

代码语言:javascript
复制
    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’管道‘跳过多次订阅。

票数 0
EN

Stack Overflow用户

发布于 2021-09-06 05:29:37

不需要嵌套多个订阅,您可以使用管道将其夷平。我根据您想要的行为修改了代码。

首先是更新用户数据。接下来,根据您发布的代码,如果我们跳过文件上传,如果不是,我们将调用upload Image调用。然后,如果上传图像调用成功,我们将调用verifySomething api调用。最后,当一切都成功时,我们从verifySomething url路由到url返回。

注意到:我添加了一个条件来检查响应参数是否有url属性,因为当我们跳过uploadImage api调用时,我们可能会得到一个没有url的响应。

代码语言:javascript
复制
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);
    }
  });
}
票数 0
EN

Stack Overflow用户

发布于 2021-09-06 06:47:48

您可以使用switchMap来解决这个问题。

代码语言:javascript
复制
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函数,则可以跳过额外的函数。

代码语言:javascript
复制
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))
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69069226

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档