Angular: вызов RxJs .switchMap () для бэкенда - оптимальная структура? - PullRequest
0 голосов
/ 17 января 2019

Какую оптимальную структуру использовать в компоненте Angular 2+, чтобы использовать мощь rxjs switchMap () при внутреннем вызове через службу?

Примечания:

  • У нас есть вложенный компонент, запускающий пользовательское событие «fetch» ​​(поэтому fromEvent(myBtn2.nativeElement, 'fetch').pipe(...); не запускается, см. Комментарий (1), поэтому мы обходим его с помощью Subject. Если есть способ использовать fetch с fromEvent() мы могли бы сэкономить Subject)

Пример реализации в StackBlitz здесь

app.component.html

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

app.component.ts

@Component({...})
export class AppComponent implements {

  @ViewChild('myBtn2', { read: ElementRef }) myBtn2: ElementRef;

  public data = 0;

  private BTN = { GET: new Subject() };
  private subs = new Subscription();

  constructor (private _ds: DataService) {}

  public ngOnInit() {
    this.setBtnLogic();
  }

  public onFetch1(ev) {
    this.subs.add(
      this._ds.getData().subscribe(res => {
        this.data = res;
        console.log('<<<', res);        // <-- logs 10 times
      })
    );
  }

  public onFetch2(ev) {
    this.BTN.GET.next(ev);
  }

  public setBtnLogic(ev?) {

    // fromEvent(this.myBtn2.nativeElement, 'fetch')   // <-- (1) this is not working
    this.BTN.GET
    .pipe(
      switchMap(p => this._ds.getData()),
      tap(data => this.data = data),
      tap(res => console.log('<<< observable ', res)), // <-- logs only the last response 
    ).subscribe();
  }

   // unsubscribes in ngOnDestroy() ...
}

1 Ответ

0 голосов
/ 18 января 2019

Правильный способ превратить ваше компонентное событие в наблюдаемое, кажется, используя Subject. Но вы можете переместить вызов next в шаблон. См .: Оператор RxJS fromEvent с выходным EventEmitter в 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
    });
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...