角度:RxJs .switchMap()调用后端-最佳结构?

时间:2019-01-17 11:57:52

标签: angular rxjs

在Angular 2+组件中使用哪种最佳结构,以便在通过服务的后端调用中利用rxjs switchMap()的功能?

注释:

  • 我们有一个嵌套的组件触发自定义的“获取”事件(因此fromEvent(myBtn2.nativeElement, 'fetch').pipe(...);不会触发,请参见注释(1),因此我们用Subject来解决它。如果有一种利用{{ 1}}与fetch,我们可以省去使用fromEvent()

StackBlitz here中的示例实现

app.component.html

Subject

app.component.ts

<app-inner #myBtn1 (fetch)="onFetch1($event)" [data]="data"></app-inner>
<app-inner #myBtn2 (fetch)="onFetch2($event)" [data]="data"></app-inner>

1 个答案:

答案 0 :(得分:0)

将组件事件变为可观察的正确方法似乎是使用Subject。但是您可以将next调用移到模板中。参见:RxJS fromEvent operator with output EventEmitter in Angular

我在您的app.component中做了一些更改:

  • 我将subject.next移至模板,随后将onFetch2的订阅移至ngInit
  • 要取消订阅,我将使用takeUntil-destroy模式。
  • 如果您在应用中的同一时间订阅,则不必使用tap,只需执行subscribe中的操作

关于switchMap的最佳用法,我不太确定您要寻找什么。只需将switchMap放在需要的pipe中。您正确使用了switchMap

https://stackblitz.com/edit/zaggi-angular-switchmap-stackoverflow-6o2d9e

<app-inner #myBtn1 (fetch)="onFetch1($event)" [data]="data"></app-inner>
<app-inner #myBtn2 (fetch)="onFetch2$.next($event)" [data]="data"></app-inner>
import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
import { DataService } from './data.service';
import { Subject, Subscription, fromEvent } from 'rxjs';
import { switchMap, map, tap, takeUntil } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
  public onFetch2$ = new Subject<string>();
  private destroy$ = new Subject<void>();

  public data = 0;

  constructor(private _ds: DataService) { }

  public ngOnInit() {
    this.onFetch2$.pipe(
      switchMap(p => this._ds.getData()),
      takeUntil(this.destroy$) // use takeUntil to unsubscribe
    ).subscribe(res => { // if you subscribe anyway you don't have to use tap
      this.data = res;
      console.log('<<< observable ', res)
    });
  }

  public ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }

  public onFetch1(ev) {
    // if getData is a HttpClient call you don't have to unsubscribe as they complete automatically
    this._ds.getData().subscribe(res => {
      this.data = res;
      console.log('<<<', res); // <-- logs 10 times upon quick click succession
    });
  }
}