Filtre Simple sur tableau de RxJS Observable

je commence mon projet avec Angular2 et les développeurs semblent recommander RxJS Observable au lieu de promesses.

j'ai réalisé, pour récupérer une liste d'éléments (épopées) à partir du serveur. Mais comment puis-je filtrer les elements en utilisant par exemple un id?

le code suivant est une extraction de mon application et montre maintenant la solution de travail finale. Espérons que cela aide quelqu'un.

@Injectable()
export class EpicService {

  private url = CONFIG.SERVER + '/app/';  // URL to web API

  constructor(private http:Http) {}

  private extractData(res:Response) {
    let body = res.json();
    return body;
  }

  getEpics():Observable<Epic[]> {
    return this.http.get(this.url + "getEpics")
      .map(this.extractData)
      .catch(this.handleError);
  }

  getEpic(id:string): Observable<Epic> {
    return this.getEpics()
      .map(epics => epics.filter(epic => epic.id === id)[0]);
  }
}

export class EpicComponent {

  errorMessage:string;
  epics:Epic[];
  epic:Epic;

  constructor(
    private requirementService:EpicService) {
  }

  getEpics() {
    this.requirementService.getEpics()
      .subscribe(
        epics => this.epics = epics,
        error => this.errorMessage = <any>error);
  }

  // actually this should be eventually in another component
  getEpic(id:string) {
    this.requirementService.getEpic(id)
        .subscribe(
        epic => this.epic = epic,
        error => this.errorMessage = <any>error);
  }
}

export class Epic {
  id: string;
  name: string;
}

je vous Remercie d'avance pour votre aide.

25
demandé sur Luka Jacobowitz 2016-06-23 15:32:04
la source

4 ответов

vous voudrez filtrer le réseau réel et non l'observable enroulé autour de lui. Vous allez donc cartographier le contenu de L'Observable (qui est un Epic[]) pour un filtrée Epic.

getEpic(id:number): Observable<Epic> {
  return this.getEpics()
     .map(epics => epics.filter(epic => epic.id === id)[0]);
}

ensuite vous pouvez subscribegetEpic et faites ce que vous voulez avec.

45
répondu Luka Jacobowitz 2016-06-23 15:42:58
la source

vous pouvez le faire en utilisant le flatMap et filter méthodes de Observable au lieu de la méthode de filtre js array dans map. Quelque chose comme:

this.getEpics() 
    .flatMap((data) => data.epics) // [{id: 1}, {id: 4}, {id: 3}, ..., {id: N}]
    .filter((epic) => epic.id === id) // checks {id: 1}, then {id: 2}, etc
    .subscribe((result) => ...); // do something epic!!!

flatMap fournira des indices singuliers pour le filtrage et ensuite vous pouvez faire avec ce qui se passe ensuite avec les résultats.

si Typographie envoie une erreur indiquant que vous ne pouvez pas comparer une chaîne et un nombre indépendamment de votre utilisation de == dans le filtre ajouter juste un + avant epic.id dans le filtre, selon les documents angulaires:

    .flatMap(...)
    .filter((epic) => +epic.id === id) // checks {id: 1}, then {id: 2}, etc
    .subscribe(...)

Exemple:

https://stackblitz.com/edit/angular-9ehje5?file=src%2Fapp%2Fapp.component.ts

19
répondu mtpultz 2018-07-11 20:58:37
la source

Observables sont paresseux. Vous devez appeler subscribe dire observable pour envoyer sa demande.

  getEpic(id:number) {
    return this.getEpics()
           .subscribe(x=>...)
           .filter(epic => epic.id === id);
  }
2
répondu Andrei Zhytkevich 2016-06-23 15:42:46
la source

Vous abonner Observable s pour obtenir les données, puisque les appels http sont async en JavaScript.

getEpic(id: number, callback: (epic: Epic) => void) {
    this.getEpics().subscribe(
        epics: Array<Epic> => {
            let epic: Epic = epics.filter(epic => epic.id === id)[0];
            callback(epic);
        }
    );
}

Vous pouvez appeler cette méthode, puis comme ceci:

this.someService.getEpic(epicId, (epic: Epic) => {
    // do something with it
});
0
répondu rinukkusu 2016-06-23 15:43:07
la source