web-dev-qa-db-fra.com

Angular 2: Comment utiliser le filtre Observable

J'ai un service qui appelle l'API comme ceci:

return this._http
        .post(appSettings.apiUrl + 'SomeController/SomeAction', params, {withCredentials: true, headers: this.headers})
        .timeoutWith(appSettings.maxTimeHttpCalls, Observable.defer(() => Observable.throw(this._feedbackService.timeout())))
        .map((response: Response) => response.json().data);

Maintenant, je veux implémenter une fonction de filtrage sur cet appel en utilisant rxjs/add/operator/filter, mais je ne peux pas le faire fonctionner correctement. 

C'est l'approche que j'ai adoptée:

return this._http
        .post(appSettings.apiUrl + 'SomeController/SomeAction', params, {withCredentials: true, headers: this.headers})
        .timeoutWith(appSettings.maxTimeHttpCalls, Observable.defer(() => Observable.throw(this._feedbackService.timeout())))
        .filter(response => response.json().data.Type === 5)
        .map((response: Response) => response.json().data);

Mais peu importe sur quoi je filtre, la boucle ngFor ne produit rien tant que le filtre est dedans. Si je l'enlève, tout fonctionne comme prévu. 

Suis-je censé ajouter le filtre avant ou après la map?

Puis-je filtrer sur le JSON de réponse de cette manière ou dois-je utiliser une autre syntaxe?

Exemple JSON

Voici un exemple de la réponse JSON:

data: [
    {
        "Type": 5,
        "Description": "Testing",
        "ID": "001525"
    }
]
6
Glenn Utter

Que filter() soit avant ou après map() dépend de ce que vous voulez faire.

Je suppose que dans votre cas, map() devrait précéder filter() car vous souhaitez d'abord décoder les données JSON, puis les filtrer. La façon dont vous l'avez maintenant ne renverra rien si la condition dans filter() est résolue en false parce que vous utilisez l'intégralité de response. Peut-être que c'est ce que vous allez faire ...

Je ne sais pas quelle est votre structure de réponse, mais je choisirais quelque chose comme cela, qui a plus de sens:

map((response: Response) => response.json().data),
filter(data => data.Type === 5),

Modifier:

J'utiliserais concatMap() avec from() pour transformer le tableau en un flux observable:

pipe(
  map(content => response.json().data),
  concatMap(arr => Observable.from(arr)),
  filter(item => item.Type === 5),
).subscribe(val => console.log(val));

Voir la démonstration en direct: http://plnkr.co/edit/nu7jL7YsExFJMGpL3YuS?p=preview

Jan 2019: Mise à jour pour RxJS 6

13
martin

Voici un autre exemple basé sur la réponse de @ martin:

  public searchMediData(searchtearm: string) : Observable<MediData[]> 
  {  

    return this.http
               .get(this.url)
               .map(response => { 
                  let data = response.json();
                  let medidata = data as MediData[];
                  return medidata;
                })
                .concatMap(array => Observable.from(array))
                .filter(medi => {
                        let searchTearmUpperCase = searchtearm.toUpperCase();
                        let mediNameUpperCase = medi.Name.toUpperCase();                       
                        return mediNameUpperCase.includes(searchTearmUpperCase);
                 })
                .toArray();
  }
2
yonexbat