最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - RxJS 6 get a filtered list of array of Observable - Stack Overflow

programmeradmin1浏览0评论

In my ThreadService class, I have a function getThreads() that return me a Observable<Thread[]> with all my threads.

Now, I would like to have another version of my function with my threads filtered by a selected theme : function getSelectedThemeThreads(theme: Theme).

I tried with the operators map and filter but I have the following error message Property 'theme' does not exist on type 'Thread[].

Below the code I am working on :

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { Thread } from '../models/thread.model';
import { Theme } from '../models/theme.model';

@Injectable({
  providedIn: 'root'
})
export class ThreadService {
  private threadsUrl = 'api/threads';

constructor(private http: HttpClient) { }

getThreads(): Observable<Thread[]> {
  return this.http.get<Thread[]>(this.threadsUrl);
}

getSelectedThemeThreads(): Observable<Thread[]> {
  return this.http.get<Thread[]>(this.threadsUrl).pipe(
    map(threads => threads),
    filter(thread => thread.theme.id === theme.id)
  );
}

Thanks in advance for your help.

In my ThreadService class, I have a function getThreads() that return me a Observable<Thread[]> with all my threads.

Now, I would like to have another version of my function with my threads filtered by a selected theme : function getSelectedThemeThreads(theme: Theme).

I tried with the operators map and filter but I have the following error message Property 'theme' does not exist on type 'Thread[].

Below the code I am working on :

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { Thread } from '../models/thread.model';
import { Theme } from '../models/theme.model';

@Injectable({
  providedIn: 'root'
})
export class ThreadService {
  private threadsUrl = 'api/threads';

constructor(private http: HttpClient) { }

getThreads(): Observable<Thread[]> {
  return this.http.get<Thread[]>(this.threadsUrl);
}

getSelectedThemeThreads(): Observable<Thread[]> {
  return this.http.get<Thread[]>(this.threadsUrl).pipe(
    map(threads => threads),
    filter(thread => thread.theme.id === theme.id)
  );
}

Thanks in advance for your help.

Share Improve this question edited Dec 10, 2018 at 11:48 Johan Rin asked Jun 2, 2018 at 17:19 Johan RinJohan Rin 1,9503 gold badges22 silver badges42 bronze badges 2
  • I think threads is an array you should do like map(threads => threads.filter) filter in this case is standard js – Whisher Commented Jun 2, 2018 at 17:24
  • filter can be a starndar js (then use inside map) or Rxjs learnrxjs.io/operators/filtering/filter.html. But..What is theme.id in thread.theme.id=== theme.id ? – Eliseo Commented Jun 3, 2018 at 14:03
Add a comment  | 

5 Answers 5

Reset to default 10

I made an example of this StackBlitz / angular6-filter-result

The main idea is to filter in the map() as the filter will get an array of objects.

getSelectedThemeThreads(theme: string): Observable<Flower[]> {
    return this.http.get<Flower[]>(this.threadsUrl).pipe(
      map(result =>
        result.filter(one => one.theme === theme)
      )
    )
  }

You were almost there. Using this map(threads => threads) does nothing but you probably wanted to use this instead:

mergeMap(threads => threads) // will turn Observable<Thread[]> into Observable<Thread>

concatMap or switchMap will work as well. The mergeMap operator will iterate the array and emit each item separately so then you can use filter() as you're doing already.

You could of course use also this:

map(threads => threads.find(thread => thread.theme.id === theme.id)),
filter(thread => thread !== undefined),

Try by using the following code.

getSelectedThemeThreads(theme): Observable<Thread[]> {
    return this.http.get<Thread[]>(this.threadsUrl)
    .map(res => res)
    .filter(thread => thread.theme.id == theme.id);
}    

Just change map(threads => threads) to mergeAll()

I think you are looking for grupoby operator:

getSelectedThemeThreads(): Observable<Thread[]> {
  return this.http.get<Thread[]>(this.threadsUrl).pipe(
    groupby(thread => thread.id),
    mergeAll(group$ => group$.pipe(
      reduce((acc, cur) =>[...acc, cur], [])
    )
  );
}

Let me know how this code works for you. In any case, if you need to play with it, a while ago a came with this example, I hope it helps you to clarify.

发布评论

评论列表(0)

  1. 暂无评论