javascript - RXJS Observable dizisi üzerinde basit filtre


Projeme Angular2 ile başlıyorum ve geliştiriciler Promises yerine RXJS Observable'ı öneriyor gibi görünüyor.

Sunucudan bir öğe listesi (epikler) almayı başardım. Ama örneğin bir kimlik kullanarak öğeleri nasıl filtreleyebilirim?

Aşağıdaki kod, uygulamamdan bir alıntıdır ve artık nihai çalışan çözümü göstermektedir. Umarız birine yardımcı olur.

@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;
}

Yardımınız için şimdiden teşekkür ederim.

Cevap #1

Gerçek diziyi filtrelemek isteyeceksiniz, onu saran observable'ı değil. Yani Observable'ın içeriğini (bu bir Epic[]) filtrelenmiş bir Epic'e dönüştüreceksiniz.

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

Sonrasında getEpic'e subscribe olabilir ve onunla istediğini yapabilirsin.

Cevap #2

Bunu map içindeki JS dizi filtreleme yöntemi yerine Observable’ın flatMap ve filter yöntemlerini kullanarak yapabilirsiniz. Şöyle bir şey:

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, filtreleme için tekil indeksler sağlayacak ve ardından sonuçlarla ne yapılacağına devam edebilirsiniz.

Eğer TypeScript, filtrede == kullanmanıza rağmen bir string ile sayı karşılaştırılamayacağını belirten bir hata veriyorsa, Angular dokümantasyonuna göre filtrede epic.id öncesine bir + ekleyin:

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

Örnek:

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

İlgili makaleler