Für eine mit Angular2 in TypeScript geschriebene Webanwendung muss ich mit RxJs Observable
s arbeiten.
Da ich noch nie zuvor RXJs verwendet habe und ich mit reaktiver Programmierung im Allgemeinen noch nicht vertraut bin, habe ich manchmal Schwierigkeiten, den richtigen Weg zu finden, um bestimmte Dinge zu tun.
Ich stehe jetzt vor einem Problem. wo ich einen Array<Observable<T>>
in einen Observable<Array<T>>
umwandeln muss.
Ich werde versuchen, es mit einem Beispiel zu erklären:
- Ich habe ein Observable
, das mir eine Liste von Users
(Observable<Array<User>>
) Gibt.
- Die Klasse User
- hat eine Funktion getPosts
, die einen Observable<Array<Post>>
Zurückgibt.
- Ich muss den Observable<Array<User>>
Einem Observable<Array<Post>>
Zuordnen, um alle Post
s innerhalb der onNext
-Funktion auszuwerten.
Ich kann leicht von Observable<Array<User>>
Zu Observable<Array<Observable<Array<Post>>>>
Mit abbildenmap((result : Array<User>) => result.map((user : User) => user.getPosts()))
und ich kann einen Array<Array<Post>>
zu einem Array<Post>
verflachen.
Ich kann jedoch nicht den richtigen Weg finden, um den Observable<Array<Observable<Array<Post>>>>
In einen Observable<Array<Array<Post>>>
Abzubilden.
Bisher habe ich die Funktion combineLatest
zusammen mit flatMap
verwendet.
Für mich schien es zu funktionieren und der von mir verwendete Editor (Atom-Editor) zeigte keinen Fehler. Jetzt verwende ich jedoch Netbeans, was mir einen Fehler in diesem Code anzeigt. Auch das Kompilieren des Codes mit "tsc" führt zu Fehlern.
Das sieht so aus:
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'.
Meine Frage lautet also:
Wie kann ich ein Array
von Observables
in ein Array
"verflachen"?
Der Operator flatMap
erlaubt dies. Ich verstehe nicht ganz, was Sie versuchen, aber ich versuche, eine Antwort zu geben ...
Wenn du alles laden willst
getPostsPerUser() {
return this.http.get('/users')
.map(res => res.json())
.flatMap((result : Array<User>) => {
return Observable.forkJoin(
result.map((user : User) => user.getPosts());
});
}
Mit Observable.forkJoin
können Sie warten, bis alle Observables Daten erhalten haben.
Der obige Code setzt voraus, dass user.getPosts()
eine beobachtbare ...
Damit erhalten Sie ein Array von Beiträgen:
this.getPostsPerUser().subscribe(result => {
var postsUser1 = result[0];
var postsUser2 = result[1];
(...)
});
Sie können die Funktion auf die gewünschte rxjs-Methode anwenden:
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 you can write it without "apply" this way:
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>
Verwenden Sie ForkJoin für dieses Array von Observables, dann ist es ein Observable des Arrays.
Hier ist ein Beispielcode, der [email protected] verwendet
import { of, forkJoin} from 'rxjs';
import { Observable } from 'rxjs'
const source:Array<Observable<String>> = [of('A'), of('B'), of('C') ];
forkJoin(source).subscribe( (x)=> console.log(x))