如何在不嵌套订阅的情况下使用 rxjs 进行第二次调用

ton*_*9uk 1 rxjs angular

嗨,我正在尝试使用 angular 9 中的 rxjs,并且我正在尝试根据 observable 的响应有条件地进行调用,但如果没有嵌套订阅,似乎无法让它工作。我已经阅读了几篇文章,包括这个这个,但我似乎无法解决我的问题。

在我的阅读中,我还阅读了这篇 SO post

单击确认按钮时触发 中的confirmed()方法DialogConfirmService

请注意,我尝试了两次以上的重构,但发布的重构是我一直在尝试的示例。

我当前的工作解决方案(我想摆脱嵌套订阅)

this.dialogConfirmService
    .confirmed()
    .pipe(take(1))
    .pipe(map(x => {
             this.isSaving = true; 
             return x; 
          })
     )
    .subscribe(confirmed => {
      if (confirmed) {
        this.myService.save('', '')
                      .pipe(take(1))
                      .subscribe(
                            (data) => this.onSuccess(data),
                            (error) => this.handleError(error)
                      );
      }
    });
Run Code Online (Sandbox Code Playgroud)

我的重构失败 1

this.dialogConfirmService
        .confirmed()
        .pipe(take(1))
        .pipe(
          map(x => {
              this.isSaving = true;
              console.log(x);
              return x;
            }
          ),
          mergeMap(cv =>
            this.myService.save(
              this.rulesetForm.controls.name.value,
              JSON.parse(this.rulesetForm.controls.definiation.value)
            )
        )).subscribe(j => this.isSaving = false);
Run Code Online (Sandbox Code Playgroud)

我的重构失败 2

onSave(): void {
    this.dialogConfirmService
            .confirmed()
            .pipe(take(1))
            .pipe(
              flatMap(confirmed => this.onConfirm(confirmed)),
            );
}

  private onConfirm(confirmed: any) {
    if (confirmed) {
      this.isSaving = true;
      this._ruleSetMapperService.save(
        this.rulesetForm.controls.name.value,
        JSON.parse(this.rulesetForm.controls.definiation.value)
      );
    } else {
      return Observable.create(function(observer) {
        observer.next(confirmed);
        observer.complete();
      });
    }
  }
Run Code Online (Sandbox Code Playgroud)

下面是调用的其他代码(为了完整起见)

对话服务

..other stuff...
export class DialogConfirmService {

  ...other stuff...

  public confirmed(): Observable<any> {

    return this.dialogRef
               .afterClosed()
               .pipe(take(1),
                     map(res => {
                        return res;
                      })
                );
  }
}
Run Code Online (Sandbox Code Playgroud)

我的储蓄服务

export class MyService {
  save(rsn: string, rsd: string): Observable<any> {
    ...other stuff... (generates the body)

    return this._http.post('myUrl', JSON.stringify(body), { headers: this.headers });
 }
}
Run Code Online (Sandbox Code Playgroud)

ion*_*t-t 7

以下是一些可以避免嵌套订阅的替代方法:

1)

this.dialogConfirmService
            .confirmed()
            .pipe(
                tap(() => (this.isSaving = true)),
                switchMap((confirmed) =>
                    confirmed ? this.myService.save('', '') : of(null)
                ),
                catchError((error) => throwError(error))
            )
            .subscribe((data) => this.onSuccess(data));

Run Code Online (Sandbox Code Playgroud)

RxJS 运算符:

tap - 用于副作用;

switchMap- 完成前一个 observable 并根据条件订阅新的 observable(switchmap操作符的组合)。请记住,即使条件为假,您也始终需要涵盖这两种情况。

catchError, throwError- 好吧,用于处理错误

2.

this.dialogConfirmService
            .confirmed()
            .pipe(
                filter((confirmed) => !!confirmed),
                tap(() => (this.isSaving = true)),
                switchMap(() => this.myService.save('', '')),
                catchError((error) => throwError(error))
            )
            .subscribe((data) => this.onSuccess(data));
Run Code Online (Sandbox Code Playgroud)

filter - 在这种情况下,只有当条件为真时,它才会订阅下一个 observable。

3.

this.dialogConfirmService
            .confirmed()
            .pipe(
                switchMap((confirmed) =>
                    iif(() => confirmed, this.myService.save('', ''))
                ),
                catchError((error) => throwError(error))
            )
            .subscribe((data) => this.onSuccess(data));
Run Code Online (Sandbox Code Playgroud)

iif- 这类似于三元运算符。它接受一个条件函数和两个 observable,但是不需要第二个 observable。

关于您进行的 http 调用,您不应该对有效负载进行字符串化。