2016-05-02 22 views
13

Per un'applicazione Web scritta con Angular2 in TypeScript, ho bisogno di lavorare con RxJs Observable s.
Come non ho mai usato rxjs prima e sono nuovo alla programmazione reattiva in generale, a volte ho qualche difficoltà a trovare il modo giusto per fare alcune cose specifiche.
Ora sto affrontando un problema. dove devo convertire un Array<Observable<T>> in un Observable<Array<T>>.
Cercherò di spiegarlo con un esempio:
- Ho un Observable, che mi dà un elenco di Users (Observable<Array<User>>)
- Il User di classe ha una funzione getPosts restituzione di un Observable<Array<Post>>.
- Ho bisogno di mappare lo Observable<Array<User>> su un Observable<Array<Post>> per valutare tutti i Post s all'interno della funzione onNext.RxJs Matrice di Observable to Array

posso facilmente mappa da Observable<Array<User>> a Observable<Array<Observable<Array<Post>>>> utilizzando
map((result : Array<User>) => result.map((user : User) => user.getPosts()))
ans posso appiattire un Array<Array<Post>> in un Array<Post>.
Tuttavia non riesco proprio a trovare il modo corretto di mappare il Observable<Array<Observable<Array<Post>>>> in un Observable<Array<Array<Post>>>
fino ad ora ho usato la funzione combineLatest insieme flatMap.
A me sembra funzionare e l'editor che ho usato (editor Atom) non ha mostrato alcun errore. Comunque ora uso Netbeans, che mi mostra un errore in questo codice. Anche compilare il codice usando "tsc" provoca errori.
L'aspetto simile a questo:

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'. 

Quindi la mia domanda è:
Come posso "appiattire" un Array di Observables in un Array?

+0

A cosa corrisponde il metodo 'getPosts'? Carica i post di un utente specifico? –

risposta

22

L'operatore flatMap consente di farlo. Non capisco pienamente ciò che si tenta di fare, ma cercherò di dare una risposta ...

Se si desidera caricare tutti i

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 consente di attendere che tutti osservabili abbiano dati ricevuti

Il codice di cui sopra presuppone che user.getPosts() restituisce un osservabile ...

Con questo, si riceverà una serie di serie di messaggi:

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

Sì, 'getPosts()' restituisce un 'Osservabile >'. Quindi immagino che sia quello che sto cercando. Lo proverò appena possibile e ti faccio sapere se ha funzionato.Grazie – Springrbua

+0

Funziona perfettamente. Mi limito a sostituire 'combineLatest' con' forkJoin'. Molte grazie! – Springrbua

3

È possibile utilizzare la funzione di applicare sul metodo rxjs si vuole, in questo modo:

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

Immagino che questo dovrebbe funzionare, ma per ora rimango con 'forkJoin'. – Springrbua