2016-05-02 19 views
13

Đối với một ứng dụng Web được viết bằng Angular2 trong TypeScript, tôi cần làm việc với RxJs Observable s.
Vì tôi chưa bao giờ sử dụng rxjs trước đây và tôi mới làm quen với chương trình hoạt động phản ứng nói chung, đôi khi tôi gặp một số khó khăn khi tìm đúng cách để thực hiện một số điều cụ thể.
Tôi hiện đang gặp sự cố. nơi tôi phải chuyển đổi một số Array<Observable<T>> thành một số Observable<Array<T>>.
tôi sẽ cố gắng giải thích nó với một ví dụ:
- Tôi có một Observable, mà mang lại cho tôi một danh sách các Users (Observable<Array<User>>)
- Các User đẳng cấp có chức năng getPosts trả lại một Observable<Array<Post>>.
- Tôi cần lập bản đồ số Observable<Array<User>> đến một số Observable<Array<Post>> để đánh giá tất cả các Post trong hàm onNext.RxJs Array of Observable to Array

tôi có thể dễ dàng lập bản đồ từ Observable<Array<User>> để Observable<Array<Observable<Array<Post>>>> sử dụng
map((result : Array<User>) => result.map((user : User) => user.getPosts()))
ans tôi có thể san bằng một Array<Array<Post>> thành một Array<Post>.
Tuy nhiên, tôi không thể tìm được cách chính xác để ánh xạ Observable<Array<Observable<Array<Post>>>> thành Observable<Array<Array<Post>>>
Cho đến bây giờ, tôi đã sử dụng chức năng combineLatest cùng với flatMap.
Đối với tôi, nó dường như hoạt động và trình soạn thảo tôi đã sử dụng (trình chỉnh sửa Atom) không hiển thị bất kỳ lỗi nào. Tuy nhiên bây giờ tôi sử dụng Netbeans, trong đó cho tôi thấy một lỗi trong mã này. Cũng biên dịch mã bằng cách sử dụng "tsc" dẫn đến lỗi.
Việc xem xét như thế này:

Argument of type '(result: Post[]) => void' is not assignable to parameter of type 'NextObserver<[Observable<Post>]> | ErrorObserver<[Observable<Post>]> | CompletionObserver<[...'. 
Type '(result: Post[]) => void' is not assignable to type '(value: [Observable<Post>]) => void'. 

Vì vậy, câu hỏi của tôi là:
Làm thế nào tôi có thể "làm phẳng" một Array của Observables thành một Array?

+0

Phương thức 'getPosts' tương ứng với điều gì? Liệu nó tải các bài viết của một người dùng cụ thể? –

Trả lời

22

Nhà điều hành flatMap cho phép thực hiện việc đó. Tôi không hoàn toàn hiểu những gì bạn cố gắng làm nhưng tôi sẽ cố gắng cung cấp một câu trả lời ...

Nếu bạn muốn tải tất cả các

getPostsPerUser() { 
    return this.http.get('/users') 
    .map(res => res.json()) 
    .flatMap((result : Array<User>) => { 
     return Observable.forkJoin(
     result.map((user : User) => user.getPosts()); 
    }); 
} 

Observable.forkJoin cho phép bạn chờ đợi cho tất cả các quan sát có đã nhận dữ liệu.

Đoạn mã trên giả định rằng user.getPosts() trả về một thể quan sát được ...

Với điều này, bạn sẽ nhận được một mảng của mảng của bài viết:

this.getPostsPerUser().subscribe(result => { 
    var postsUser1 = result[0]; 
    var postsUser2 = result[1]; 
    (...) 
}); 
+1

Yea 'getPosts()' trả về một 'Quan sát >'. Vì vậy, tôi đoán đó là những gì tôi đang tìm kiếm. Tôi sẽ thử nó ra càng sớm càng tốt và cho bạn biết nếu nó hoạt động.Cảm ơn – Springrbua

+0

Hoạt động hoàn hảo. Tôi chỉ đội mũ để thay thế 'combinedLatest' bằng' forkJoin'. Cảm ơn rất nhiều! – Springrbua

3

Bạn có thể sử dụng chức năng áp dụng vào phương pháp rxjs bạn muốn, như thế này:

const source1 = Rx.Observable.interval(100) 
 
    .map(function (i) { return 'First: ' + i; }); 
 

 
const source2 = Rx.Observable.interval(150) 
 
    .map(function (i) { return 'Second: ' + i; }); 
 

 
const observablesArray = [source1, source2]; 
 

 
const sources = Rx.Observable.combineLatest 
 
.apply(this, observablesArray).take(4) 
 

 
// or 
 

 
const sources = Rx.Observable 
 
       .combineLatest(...observablesArray) 
 
       .take(4) 
 

 
sources.subscribe(
 
    (response) => { 
 
    console.log(response); 
 
    } 
 
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.1/Rx.min.js"></script>

+0

Tôi đoán điều này sẽ làm việc, nhưng tôi sẽ gắn bó với 'forkJoin' bây giờ. – Springrbua