Dans mon application, j'ai quelque chose comme:
this._personService.getName(id)
.concat(this._documentService.getDocument())
.subscribe((response) => {
console.log(response)
this.showForm()
});
//Output:
// [getnameResult]
// [getDocumentResult]
// I want:
// [getnameResult][getDocumentResult]
Ensuite, j'obtiens deux résultats séparés, d'abord du _personService
, Puis du _documentService
. Comment puis-je attendre les deux résultats avant d'appeler this.showForm()
pour terminer puis manipuler les résultats de chacun?.
J'ai déjà suggéré l'utilisation de la méthode Zip
. Cependant, depuis lors, je me suis retrouvé à utiliser combineLatest
à la place. Alors décidé d'ajouter combineLatest
.
CombineLatest
émet les dernières valeurs émises par les observables. Alors que Zip
la méthode émet les éléments émis dans l'ordre sequence.
Par exemple, si l’observable n ° 1 émet son élément rd et que l’observable n ° 2 a émis son élément 5th. Le résultat en utilisant la méthode Zip
sera les rd valeurs émises des deux observables
.
Dans cette situation, le résultat en utilisant combineLatest
sera le 5th et rd. qui se sent plus naturel.
De reactiveX documentation :
Chaque fois qu'une entrée Observable émet une valeur, elle calcule une formule en utilisant les dernières valeurs de toutes les entrées, puis émet la sortie de cette formule.
// 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();
})
La méthode Observable.Zip est expliquée dans documentation reactiveX :
Combine plusieurs observables pour créer un observable dont les valeurs sont calculées à partir des valeurs, dans l'ordre, de chacun des observables en entrée.
// 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();
})
Le dernier paramètre, où nous avons fourni une fonction, (name: string, document: string) => ({name, document})
est facultatif. Vous pouvez le sauter ou effectuer des opérations plus complexes:
Si le dernier paramètre est une fonction, cette fonction est utilisée pour calculer la valeur créée à partir des valeurs d'entrée. Sinon, un tableau des valeurs en entrée est renvoyé.
Donc, si vous sautez la dernière partie, vous obtenez un tableau:
// 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();
})
Utilisez la méthode forkJoin()
des observables. Voir ce lien pour référence
Depuis le RXJS docs
Cet opérateur est mieux utilisé lorsque vous avez un groupe d'observables et que vous ne vous souciez que de la valeur finale émise de chacun. Un cas d'utilisation courant pour cela est si vous souhaitez émettre plusieurs demandes lors du chargement de la page (ou un autre événement) et que vous souhaitez agir uniquement lorsqu'une réponse a été reçue pour tous. De cette façon, cela ressemble à la façon dont vous pourriez utiliser Promise.all
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 extrait de: https://coryrylan.com/blog/angular-multiple-http-requests-with-rxjs
Les opérateurs RxJS pour les nuls: forkJoin, Zip, combineLatest, withLatestFrom m'ont beaucoup aidé. Comme son nom l'indique, il décrit les opérateurs de combinaison suivants:
N'importe lequel d'entre eux pourrait être ce que vous recherchez, cela dépend du cas. Consultez l'article pour plus d'informations.
Pour moi, ce échantillon était la meilleure solution.
const source = Observable.interval(500);
const example = source.sample(Observable.interval(2000));
const subscribe = example.subscribe(val => console.log('sample', val));
Donc .. seulement lorsque second (exemple) émet - vous verrez la dernière valeur émise de premier (source).
Dans ma tâche, j'attends la validation du formulaire et tout autre événement DOM.
Regardez la méthode 'combineLatest', cela pourrait être approprié ici. 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()
})
Vous pouvez utiliser "Zip" ou "tampon" comme suit.
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}`));