Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
708 views
in Technique[技术] by (71.8m points)

rxjs - Angular 2: How to use Observable filter

I have a service that calls the API like this:

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

Now I want to implement a filter function on that call using rxjs/add/operator/filter, but I can't get it to work properly.

This is the approach I have taken:

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

But no matter what I filter on, the ngFor loop produces nothing as long as the filter is in there. If I remove it, everything works as expected.

Am I supposed to add the filter before or after the map?

Can I filter on the response JSON like that, or do I need to use another syntax?

Example JSON

Here's an example of what the response JSON looks like:

data: [
    {
        "Type": 5,
        "Description": "Testing",
        "ID": "001525"
    }
]
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Whether filter() should be before or after map() depends on what you want to do.

I guess in your case map() should go before filter() because you want to first decode data from JSON and then filter it. The way you have it now won't return anything if the condition in filter() resolves to false because you're using in on the entire response. Maybe this is what you're going for...

I don't know what your response structure is but I'd go with something like this which makes more sense:

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

Edit:

I'd use concatMap() with from() to transform the array to an Observable stream:

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

See live demo: http://plnkr.co/edit/nu7jL7YsExFJMGpL3YuS?p=preview

Jan 2019: Updated for RxJS 6


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...