112 votes

Comment «attendre» deux observables dans RxJS

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 le _personService et ensuite le _documentService . Comment puis-je attendre les deux résultats avant d'appeler this.showForm() pour terminer puis manipuler les résultats de chacun?

148voto

Hamid Asghari Points 1878

Mise À Jour: Oct, 2018

J'ai déjà proposé l'utilisation d' zip méthode. Cependant, depuis lors, je me suis retrouvé à l'aide d' combineLatest à la place. Donc décidé d'ajouter combineLatest.

CombineLatest émet de la dernière émises valeurs à partir des observables. Alors qu' zip méthode émet émis des éléments dans la séquence de commande.

Par exemple, si observables #1 émet son 3ème élément observable et #2 a émis son 5ème élément. Le résultat à l'aide d' zip méthode sera la 3ème émises valeurs à la fois observables.

Dans cette situation, le résultat à l'aide d' combineLatest sera le 5ème et 3ème. qui se sent de plus naturel.


combineLatest(observables)

De reactiveX de la documentation:

Chaque fois qu'une entrée Observables émet une valeur, on calcule une formule en utilisant les dernières valeurs de toutes les entrées, puis émet de 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();
       })

Observable.zip(observables)

Observable.zip la méthode est expliquée dans reactiveX de la documentation:

Combine plusieurs Observables pour créer une Observable dont les valeurs sont calculées à partir des valeurs, dans l'ordre, de chacun de ses intrants Observables.

// 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();
       })

une note de côté (s'applique pour les deux méthodes)

Le dernier paramètre, où nous avons fourni une fonction, (name: string, document: string) => ({name, document}) est facultatif. Vous pouvez ignorer, ou faire 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 d'entrée est retourné.

Donc, si vous passez 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();
       })

57voto

Prathmesh Dali Points 1112

Utiliser forkJoin() méthode des observables. Suivez ce lien pour référence

À partir de la RXJS docs

Cet opérateur est utilisé au mieux quand vous avez un groupe de phénomènes observables et se soucient seulement de la finale émise valeur de chaque. Une utilisation de ce est si vous souhaitez envoyer plusieurs demandes au chargement de la page (ou d'un autre événement) et voulez seulement de prendre des mesures lorsqu'une réponse a été receieved pour tous. De cette façon, il est semblable à la façon dont vous pouvez utiliser Promesse.tous

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 d': https://coryrylan.com/blog/angular-multiple-http-requests-with-rxjs

24voto

nyxz Points 419

Le RxJS Opérateurs pour les Nuls: forkJoin, zip, combineLatest, withLatestFrom m'a beaucoup aidé. Comme le nom l'indique, il décrit la combinaison suivante des opérateurs:

L'un d'eux pourrait être la chose que vous cherchez, selon le cas. Consultez l'article pour plus d'info.

2voto

Pour moi, cet é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.

2voto

Tal Points 199

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()
    })
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X