angular - När ska man använda RxJS Observable<Object[]> och Observable<Object>?


Med Angular 6 definierade jag mina tjänster baserat på hero-appen. Om en metod ska returnera flera värden returnerar jag alltid en Observable<A[]> och om jag förväntar mig en enskild retur, till exempel om metoden är getById, returnerar jag Observable<A>.

Problemet är att idag ville jag göra en groupBy() på en av de returnerade arrayen av värden och alla exempel jag kunde hitta använder bara Observable<A> istället för Observable<A[]>, som detta exempel. Dessutom, om man tittar på svaren här (jag provade det, detta fungerar bara på ~Observable<A>) och RxJS-introduktionen (Observable: represents the idea of an invokable collection of future values or events.), verkar det som att jag borde ha använt Observable<A> för samlingar som servern returnerar, men vad använder jag då för enstaka värden?

Exempel på tjänster:

  all(): Observable<T[]> {
    return this.httpClient.get<T[]>(this.urls().allURL());
  }

  paginate(pageRequest: any): Observable<Page<T>> {
    return this.httpClient.post<Page<T>>(this.urls().paginateURL(), pageRequest);
  }

  findOneById(id: number): Observable<T> {
    return this.httpClient.get<T>(this.urls().byIdURL(id));
  }

Uppdatering :

Jag gjorde ett exempelprojekt. Jag kan arbeta med array-observables på det här sättet, men då behöver jag alltid en mergeMap. Jag förstår att om jag använder Observable<A[]>, kommer jag få alla värden på en gång, eftersom de finns i en array, men om jag använder Observable<A> får jag dem en i taget, vilket är anledningen till att jag till exempel inte kan använda det i en *ngFor (förväntar sig en array). Frågan är om jag alltid ska använda A[] när servern synkront returnerar en samling och A om jag arbetar med asynkron data, eller om jag även behöver beakta andra scenarier.

import { Component, OnInit } from '@angular/core';
import { Observable, from, of, GroupedObservable } from 'rxjs';
import { distinct, map, mergeMap, toArray, groupBy } from 'rxjs/operators';

export class ModelA {
  id: number;
  name: string;
}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  name = 'Angular';

  models: Observable<ModelA[]>;
  distinctModels: Observable<ModelA[]>;
  groupedModels: Observable<ModelA[][]>;

  ngOnInit() {
    this.loadData();
  }

  loadData(): void {
    this.models = of([
      {id: 1, name: 'Name A'},
      {id: 2, name: 'Name A'},
      {id: 3, name: 'Name B'},
      {id: 4, name: 'Name C'}
    ]);

    this.distinctModels = this.models
        .pipe(
          mergeMap(models => models),
          distinct(m => m.name),
          toArray()
        );
    this.distinctModels.subscribe( m => console.log(m));

    this.groupedModels = this.models
        .pipe(
          mergeMap(models =>models),
          groupBy(model => model.name),
          mergeMap(toArray()),
          toArray()
        );
    this.groupedModels.subscribe( m => console.log(m));
  }
}

Svar #1

Jag är inte säker på vad du vill. Om det är en Grupp bara Observable< any[][] >

export class AppComponent implements OnInit {
  people: any[] = [
   { name: 'Sue', age: 25 },
   { name: 'Joe', age: 30 },
   { name: 'Frank', age: 25 },
   { name: 'Sarah', age: 35 }
  ];
  result:any[][];

  ngOnInit()
  {
    this.myObservable().subscribe(res=>{
      this.result=res;
    })
  }

  myObservable():Observable<any[][]>
  {
    return from(this.people).pipe(
      groupBy((person:any)=>person.age),
      mergeMap(group=>group.pipe(toArray())),
      toArray());
  }

Och .html

  <div *ngFor="let ages of result">
    <strong>{{ages[0].age}}</strong>
    <div *ngFor="let item of ages">
      {{item.name}}
    </div>
  </div>