In meiner App habe ich so etwas wie:
this._personService.getName(id)
.concat(this._documentService.getDocument())
.subscribe((response) => {
console.log(response)
this.showForm()
});
//Output:
// [getnameResult]
// [getDocumentResult]
// I want:
// [getnameResult][getDocumentResult]
Dann bekomme ich zwei getrennte Ergebnisse, zuerst das _personService
und dann das _documentService
. Wie kann ich auf beide Ergebnisse warten, bevor der Aufruf abgeschlossen ist this.showForm()
, und dann die Ergebnisse der einzelnen bearbeiten?
concat
Antworten:
Letzte Aktualisierung: Mai 2020.
combinLatest (Observablen)
Aus der reactiveX- Dokumentation :
(Update: Mai 2020) Während das andere Beispiel gültig bleibt, gibt es hier eine neue Syntax:
// Observables to combine const name$ = this._personService.getName(id); const document$ = this._documentService.getDocument(); name$.combineLatest(document$, (name, document) => {name, document}) .subscribe(pair => { this.name = pair.name; this.document = pair.document; this.showForm(); })
combinLatest (Observables) (alternative Syntax):
// Observables to combine const name$ = this._personService.getName(id); const document$ = this._documentService.getDocument(); combineLatest(name$, document$, (name, document) => ({name, document})) .subscribe(pair => { this.name = pair.name; this.document = pair.document; this.showForm(); })
zip vs combinLatest
(Update: Okt. 2018) Ich habe zuvor die Verwendung der
zip
Methode vorgeschlagen. Für einige AnwendungsfällecombineLatest
hat dies jedoch einige Vorteile gegenüberzip
. Daher ist es wichtig, die Unterschiede zu verstehen.CombineLatest
gibt die zuletzt emittierten Werte von Observablen aus. Während diezip
Methode die ausgegebenen Elemente in der Reihenfolge ihrer Reihenfolge ausgibt .Zum Beispiel, wenn Observable # 1 sein drittes Element ausstrahlt und Observable # 2 sein 5. Element ausgibt. Das Ergebnis unter Verwendung der
zip
Methode ist der 3. emittierte Wert von beidenobservables
.In dieser Situation ist das Ergebnis
combineLatest
die 5. und 3 .. das fühlt sich natürlicher an.Observable.zip (Observables)
(Ursprüngliche Antwort: Jul, 2017) Die Observable.zip-Methode wird in der reactiveX-Dokumentation erläutert:
// Observables to combine const name$ = this._personService.getName(id); const document$ = this._documentService.getDocument(); Observable .zip(name$, document$, (name: string, document: string) => ({name, document})) .subscribe(pair => { this.name = pair.name; this.document = pair.document; this.showForm(); })
eine Randnotiz (gilt für beide Methoden)
Der letzte Parameter, für den wir eine Funktion bereitgestellt haben,
(name: string, document: string) => ({name, document})
ist optional. Sie können es überspringen oder komplexere Vorgänge ausführen:Wenn Sie also den letzten Teil überspringen, erhalten Sie ein Array:
// Observables to combine const name$ = this._personService.getName(id); const document$ = this._documentService.getDocument(); Observable .zip(name$, document$) .subscribe(pair => { this.name = pair['0']; this.document = pair['1']; this.showForm(); })
quelle
Verwenden Sie die
forkJoin()
Methode der Observablen. Überprüfen Sie diesen Link als ReferenzAus den RXJS- Dokumenten
Observable.forkJoin([character, characterHomeworld]).subscribe(results => { // results[0] is our character // results[1] is our character homeworld results[0].homeworld = results[1]; this.loadedCharacter = results[0]; });
Code entnommen aus: https://coryrylan.com/blog/angular-multiple-http-requests-with-rxjs
quelle
Die RxJS-Operatoren für Dummies: ForkJoin, Zip, CombineLatest, WithLatestFrom haben mir sehr geholfen. Wie der Name schon sagt, werden die folgenden Kombinationsoperatoren beschrieben:
Jeder von ihnen könnte das sein, wonach Sie suchen, hängt vom Fall ab. Weitere Informationen finden Sie im Artikel.
quelle
Verbesserung der Hamid Asghari-Antwort, die direkte Argumentzerlegung verwendet und automatisch Typen hinzufügt (wenn Sie Typoskript verwenden)
const name$ = this._personService.getName(id); const document$ = this._documentService.getDocument(); combineLatest([name$, document$]).subscribe(([name, document]) => { this.name = name; this.document = document; this.showForm(); });
BONUS : Sie können Fehler auch wie folgt behandeln
Code-Snippet anzeigen
import { combineLatest, of } from 'rxjs'; //... const name$ = this._personService.getName(id); const document$ = this._documentService.getDocument(); combineLatest([ name$.pipe( catchError( () => of(null as string ) ) ), document$.pipe( catchError( () => of(null as Document) ) ), // 'Document' is arbitrary type ]).subscribe(([name, document]) => { this.name = name; // or null if error this.document = document; // or null if error this.showForm(); });
quelle
Für mich war diese Probe die beste Lösung.
const source = Observable.interval(500); const example = source.sample(Observable.interval(2000)); const subscribe = example.subscribe(val => console.log('sample', val));
Also .. nur beim zweiten (Beispiel) emittieren - Sie sehen den zuletzt emittierten Wert von first (Quelle).
In meiner Aufgabe warte ich auf die Formularüberprüfung und andere DOM-Ereignisse.
quelle
Schauen Sie sich die Methode 'combinLatest' an, die hier möglicherweise angebracht ist. http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-combineLatest
const { Observable } = Rx const name$ = this._personService.getName(id); const document$ = this._documentService.getDocument(); Observable .combineLatest(name$, document$, (name, document) => ({ name, document })) .first() // or not, implementation detail .subscribe(({ name, document }) => { // here we have both name and document this.showForm() })
quelle
Sie können 'zip' oder 'buffer' wie folgt verwenden.
function getName() { return Observable.of('some name').delay(100); } function getDocument() { return Observable.of('some document').delay(200); } // CASE1 : concurrent requests Observable.zip(getName(), getDocument(), (name, document) => { return `${name}-${document}`; }) .subscribe(value => console.log(`concurrent: ${value}`)); // CASE2 : sequential requests getName().concat(getDocument()) .bufferCount(2) .map(values => `${values[0]}-${values[1]}`) .subscribe(value => console.log(`sequential: ${value}`));
quelle