Ich beginne mein Projekt mit Angular2 und die Entwickler scheinen RXJS Observable anstelle von Promises zu empfehlen.
Ich habe es geschafft, eine Liste von Elementen (Epics) vom Server abzurufen. Aber wie kann ich die Elemente filtern, indem ich zum Beispiel eine ID verwende?
Der folgende Code ist ein Auszug aus meiner App und zeigt nun die endgültige funktionierende Lösung. Hoffen wir, dass es jemandem hilft.
@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;
}
Vielen Dank im Voraus für deine Hilfe.
Sie möchten das tatsächliche Array filtern und nicht das um es gewickelte Observable. So ordnen Sie den Inhalt des Observable (das ist ein Epic[]
) zu einem gefilterten Epic
.
getEpic(id: string): Observable<Epic> {
return this.getEpics()
.map(epics => epics.filter(epic => epic.id === id)[0]);
}
Danach können Sie subscribe
bis getEpic
und damit machen, was Sie wollen.
Sie können dazu die Methoden flatMap
und filter
von Observable
anstelle der JS-Array-Filtermethode in map
verwenden. So etwas wie:
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
liefert singuläre Indizes zum Filtern und dann können Sie mit den Ergebnissen weitermachen, was auch immer als nächstes passiert.
Wenn TypeScript einen Fehler ausgibt, der anzeigt, dass Sie eine Zeichenfolge und eine Zahl unabhängig von der Verwendung von ==
Im Filter nicht vergleichen können, fügen Sie einfach +
Vor epic.id
Im Filter ein. gemäß den Angular docs:
.flatMap(...)
.filter((epic) => +epic.id === id) // checks {id: 1}, then {id: 2}, etc
.subscribe(...)
Beispiel:
https://stackblitz.com/edit/angular-9ehje5?file=src%2Fapp%2Fapp.component.ts
ursprüngliche Antwort mit einem Fix: Observables
sind faul. Sie müssen subscribe
aufrufen, um einem observable
mitzuteilen, dass er seine Anfrage senden soll.
getEpic(id:number) {
return this.getEpics()
.filter(epic => epic.id === id)
.subscribe(x=>...);
}
Update auf Rxjs 6:
import {filter} from 'rxjs/operators';
getEpic(id:number) {
return this.getEpics()
.pipe(filter(epic => epic.id === id))
.subscribe(x=>...);
}
Sie müssen Observable
s abonnieren, um die Daten abzurufen, da http-Aufrufe in JavaScript asynchron sind.
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);
}
);
}
Sie können diese Methode dann folgendermaßen aufrufen:
this.someService.getEpic(epicId, (epic: Epic) => {
// do something with it
});