Prosty filtr na tablicy Rxjs obserwowalny

Zaczynam swój projekt od Angular2 i deweloperzy wydają się polecać Rxjs Observable zamiast obietnic.

Udało mi się pobrać listę elementów (epic) z serwera. Ale jak mogę filtrować elments używając na przykład id?

Poniższy kod jest ekstrakcją z mojej aplikacji i pokazuje teraz ostateczne rozwiązanie robocze. Miejmy nadzieję, że to komuś pomoże.

@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;
}
Z góry dziękuję za pomoc.
Author: Luka Jacobowitz, 2016-06-23

4 answers

Będziesz chciał filtrować rzeczywistą tablicę, a nie obserwowalną owiniętą wokół niej. Więc zmapujesz zawartość Obserwowalnej (która jest Epic[]) na filtrowaną Epic.

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

Potem możesz subscribe do getEpic i robić z tym, co chcesz.

 45
Author: Luka Jacobowitz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-23 12:42:58

Możesz to zrobić używając metod flatMap i filter Observable zamiast metody js array filter w map. Coś w stylu:

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 zapewni pojedyncze wskaźniki do filtrowania, a następnie możesz przejść do tego, co dzieje się dalej z wynikami.

Jeśli TypeScript wyświetli błąd wskazujący, że nie możesz porównać ciągu znaków i liczby niezależnie od użycia == w filtrze, po prostu dodaj + przed epic.id w filtrze, na kąt docs:

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

Przykład:

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

 19
Author: mtpultz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-11 17:58:37

Observables są leniwi. Musisz zadzwonić subscribe, aby powiedzieć observable, Aby wysłać swoją prośbę.

  getEpic(id:number) {
    return this.getEpics()
           .subscribe(x=>...)
           .filter(epic => epic.id === id);
  }
 2
Author: Andrei Zhytkevich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-23 12:42:46

Musisz zapisać się na Observable s, aby uzyskać dane, ponieważ połączenia http są asynchroniczne w 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);
        }
    );
}

Możesz wywołać tę metodę w następujący sposób:

this.someService.getEpic(epicId, (epic: Epic) => {
    // do something with it
});
 0
Author: rinukkusu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-23 12:43:07