web-dev-qa-db-fra.com

Comment forcer les observables à s'exécuter en séquence?

Je passe du monde Promise au monde observable. Une chose que je fais habituellement avec Promise est d'enchaîner une série de tâches et de les exécuter en séquence. Par exemple, j'ai trois tâches: printLog1() pour imprimer 1 sur la console, printLog23() pour imprimer 2 et 3 sur la console, et printLog4() pour imprimer 4.

Quand je veux imprimer 1-2-3-4, j'écrirais une chaîne de promesses comme

printLog1()
  .then(() => {
    printLog23();
  })
  .then(() => {
    printLog4();
  });

Maintenant, je veux la même fonctionnalité avec Observable et je peux réécrire la fonction printLog() dans un observable comme

printLog1 = Rx.Observabale.of(1).map((i) => console.log(i));
printLog23 = Rx.Observabale.of(2, 3).map((i) => console.log(i));
printLog4 = Rx.Observabale.of(4).map((i) => console.log(i));

Ensuite, j'ai trois observables qui émettent des valeurs différentes vers la console. Comment les chaîner pour que ces trois observables s'exécutent dans l'ordre et impriment 1-2-3-4?

24
Haoliang Yu

Si vous voulez être sûr que l'ordre des émissions est le même que l'ordre dans lequel vous avez spécifié les observables source, vous pouvez utiliser les opérateurs concat ou concatMap.

Le concat* les opérateurs ne s'abonnent à un observable qu'après la fin de l'observable précédent (il fonctionne également avec Promises, voir http://reactivex.io/rxjs/class/es6/MiscJSDoc.js~ObservableInputDoc.html ).

Dans votre cas, cela ressemblerait à ceci:

import { concat } from 'rxjs'; // Note, concat from 'rxjs', is not the same as concat from 'rxjs/operators'

concat(printLog1, printLog23, printLog4);

... ou avec concatMap si la demande d'une promesse dépend de la réponse de la promesse précédente:

printLog1.pipe(
  concatMap(response => ...),
  concatMap(response => ...),
);

... ou lorsque la commande n'a pas d'importance, vous pouvez utiliser merge qui souscrit à tous les Observables/Promesses immédiatement et réémet leurs résultats à leur arrivée:

merge(printLog1, printLog23, printLog4);

Jan 2019: mis à jour pour RxJS 6

37
martin