【问题标题】:Using RxJS in Angular with conditional / combined subscriptions在 Angular 中使用带有条件/组合订阅的 RxJS
【发布时间】:2022-01-06 21:21:16
【问题描述】:

在我的 Angular 应用程序中,我有一个类似这样的 API 服务,其中包含两种方法:

addComment(id: string, comment: string): Observable<any> {
    return this.http.post(`api/${encodeURIComponent(id)}/comment`, { comment }).pipe(
      map(this.apiUtils.extractData)
    );
  }


closeAccount(id: string): Observable<any> {
    return this.http.post(`api/${encodeURIComponent(id)}/closeaccount`, {}).pipe(
      map(this.apiUtils.extractData)
    );
}

现在在我的应用程序中,我有一个可以关闭用户帐户的组件,如果添加了评论,我希望在关闭帐户之前添加评论,但这是有条件的,有时用户不需要添加在关闭帐户之前发表评论。在我的组件文件中,我为此创建了一个方法,但是我有点卡住了……这是我的组件代码,我在其中收集用户数据并从表单中发表评论。如果我们有评论,我们会调用 api 来添加评论,当它解决时,我会调用 API 来关闭帐户。如果没有提交评论,我只需调用 api 来关闭帐户。这很好,但很难雄辩!请注意,我已减少代码以提高可读性。

constructor(private formBuilder: FormBuilder,
            public apiService: ApiService) {}

// i have omitted the code where I create my form and validation

closeAccount(): void {
    // get values from my form
    const id = this.closeAccountForm.controls.id.value;
    const comment = this.closeAccountForm.controls.closeAccountComment.value; 

    if (comment) {
        this.apiService.addComment(id, comment).subscribe(() => {
            this.apiService.closeAccount(id).subscribe(() => {
                // now do something
            });
        })
    } else {  
        this.apiService.closeAccount(id).subscribe(() => {
            // now do something
        });
    }
}

我想知道是否可以减少代码并防止重复调用 closeAccount 方法。 RxJS 是否为我提供了一种在方法中应用条件逻辑的方法?我上面的作品但很丑!

我目前正在阅读文档,但有时人们可以更快地提供答案。如果我找到答案/解决方案,我将在此处提供。提前谢谢了。如果我的措辞不好,请说出来,我会修改我的问题。

【问题讨论】:

  • 为防止代码重复,只需将 closeAccount 调用提取到另一个函数即可。从您所展示的内容来看,我认为 if-else 确实有意义。您正在根据用户输入执行不同的操作,所以这里没有错。如果您不需要添加评论订阅中的评论值,您可以做的一件事是使用 addComment 中的 switchMap 管道切换到 closeAccount。

标签: angular rxjs angular-observable


【解决方案1】:

试试这个:

const preCloseAction = comment ? this.apiService.addComment(...) : of(null);

preCloseAction.pipe(
  switchMap(() => this.apiService.closeAccount(id))
).subscribe(() => {
  // now do something
})

或者,如果在 closeAccount 调用期间评论的结果无关紧要

concat(
  !comment ? EMPTY : this.apiService.addComment(...),
  this.apiService.closeAccount(id)
).pipe(last()).subscribe(() => {
  // now do something
})

【讨论】:

  • concat() 选项将在有评论时触发 2 个下一个通知(每个 observable 一个)。因此,如果您只想触发一次do something,如果您对closeAccount 响应感兴趣,则必须在订阅前添加.pipe(last()),或者如果没有,则为complete 通知提供观察者有兴趣。
  • 你是对的
【解决方案2】:

如果请求的顺序无关紧要,您可以从 if 子句中删除调用并删除 else。

closeAccount(): void {
    ... 

    if (comment) {
        this.apiService.addComment(id, comment).subscribe(); 
    } 

    this.apiService.closeAccount(id).subscribe(() => {
       // now do something
    });
}

如果订单很重要,您可以根据条件为请求设置 observable,然后对结果调用 subscribe。

 closeAccount(): void {
    ...
    const request = comment 
      ?  this.apiService.addComment(id, comment).pipe(
           switchMap(_ => this.apiService.closeAccount(id))
         ) 
      : this.apiService.closeAccount(id);

    request.subscribe(() => {
       // now do something
    });
}

干杯

【讨论】:

    猜你喜欢
    • 2021-12-14
    • 2021-03-03
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    • 2018-12-11
    相关资源
    最近更新 更多