2016-06-23 37 views
17

Tôi đang bắt đầu dự án của mình với Angular2 và các nhà phát triển dường như đề xuất RXJS Observable thay vì Promises.Bộ lọc đơn giản trên mảng RXJS Quan sát

Tôi đã đạt được để lấy danh sách các phần tử (sử thi) từ máy chủ. Nhưng làm thế nào tôi có thể lọc các elments bằng cách sử dụng ví dụ như một id?

Mã sau đây là trích xuất từ ​​ứng dụng của tôi và hiển thị bây giờ là giải pháp làm việc cuối cùng. Hãy hy vọng nó giúp ai đó.

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

Cảm ơn trước sự giúp đỡ của bạn.

Trả lời

30

Bạn sẽ muốn lọc mảng thực và không được quan sát xung quanh nó. Vì vậy, bạn sẽ lập bản đồ nội dung của Đài quan sát (là Epic[]) thành Epic được lọc.

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

Sau đó, sau đó bạn có thể subscribe-getEpic và làm bất cứ điều gì bạn muốn với nó.

+0

Có vẻ đơn giản nhưng: Lỗi: (33, 42) TS2365: Toán tử '===' không thể áp dụng cho các loại 'chuỗi' và 'số'. Tôi sẽ cập nhật câu hỏi, để hiển thị toàn bộ thành phần và mối quan hệ dịch vụ. – Johannes

+0

Vâng, nếu đó là sau đó bạn chỉ có thể chuyển đổi từ chuỗi thành số hoặc số thành chuỗi :) –

3

Observables lười. Bạn phải gọi subscribe để yêu cầu observable gửi yêu cầu của mình.

getEpic(id:number) { 
    return this.getEpics() 
      .subscribe(x=>...) 
      .filter(epic => epic.id === id); 
    } 
0

Bạn phải đăng ký số Observable để nhận dữ liệu, vì các cuộc gọi http không đồng bộ trong 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); 
     } 
    ); 
} 

Bạn có thể gọi phương pháp mà sau đó như thế này:

this.someService.getEpic(epicId, (epic: Epic) => { 
    // do something with it 
}); 
9

Bạn có thể làm điều này bằng cách sử dụng flatMapfilter phương pháp Observable thay vì phương pháp lọc mảng JS trong map. Một cái gì đó như:

this.getEpics() // [{id: 1}, {id: 4}, {id: 3}, ..., {id: N}] 
    .flatMap((data) => data.epics) 
    .filter((epic) => epic.id === id) // checks {id: 1}, then {id: 2}, etc 
    .subscribe((result) => ...); // do something epic!!! 

flatMap sẽ cung cấp chỉ số đơn lẻ cho việc lọc và sau đó bạn có thể nhận ra với bất cứ điều gì xảy ra tiếp theo với kết quả.

Nếu nguyên cảo ném một lỗi cho biết bạn không thể so sánh một chuỗi và một số bất kể việc bạn sử dụng == trong bộ lọc chỉ cần thêm một + trước epic.id trong bộ lọc, mỗi tài liệu góc:

.flatMap(...) 
    .filter((epic) => +epic.id === id) // checks {id: 1}, then {id: 2}, etc 
    .subscribe(...) 
Các vấn đề liên quan