web-dev-qa-db-ja.com

Angular 2:Observableフィルターの使用方法

このようなAPIを呼び出すサービスがあります。

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);

ここで、rxjs/add/operator/filterを使用してその呼び出しにフィルター関数を実装したいのですが、適切に動作させることができません。

これは私が取ったアプローチです:

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);

しかし、何をフィルターしても、ngForループは、フィルターがそこにある限り何も生成しません。削除すると、すべてが期待どおりに機能します。

mapの前後にフィルターを追加することになっていますか?

そのような応答JSONでフィルタリングできますか、または別の構文を使用する必要がありますか?

JSONの例

応答JSONの例を次に示します。

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

filter()map()の前にあるか後にあるかは、何をしたいかによって異なります。

あなたの場合、map()filter()の前に行くべきだと思います。最初にJSONからデータをデコードし、それからフィルタリングしたいからです。 filter()の条件がfalseに解決する場合、response全体で使用しているため、現在の方法では何も返されません。たぶんこれはあなたがしようとしているものです...

私はあなたの応答構造が何であるかわかりませんが、もっと理にかなっている次のようなものを使います:

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

編集:

concatMap()from()を使用して、配列をObservableストリームに変換します。

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

ライブデモを参照してください: http://plnkr.co/edit/nu7jL7YsExFJMGpL3YuS?p=preview

2019年1月:RxJS 6用に更新

16
martin

@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