Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force observables to execute in sequence?

Tags:

rxjs

rxjs5

I am moving from the Promise world to the Observable world. One thing I usually do with Promise is to chain a series of tasks and make them run in sequence. For example, I have three tasks: printLog1() to print 1 to the console, printLog23() to print 2 and 3 to the console, and printLog4() to print 4.

When I want to print 1-2-3-4, I would write a promise chain like

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

Now I want the same functionality with Observable and I can rewrite the printLog() function into an Observable like

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));

Then I have three observables that emits different values to the console. How do I chain them so that these three observables would run in order and print 1-2-3-4?

like image 582
Haoliang Yu Avatar asked Apr 11 '17 04:04

Haoliang Yu


People also ask

Is Forkjoin sequential?

In parallel computing, the fork–join model is a way of setting up and executing parallel programs, such that execution branches off in parallel at designated points in the program, to "join" (merge) at a subsequent point and resume sequential execution.

Which method is used in RxJS to work on multiple operators together in sequential order?

ConcatAll This operator combines all emitted inner streams and just as with plain concat sequentially produces values from each stream.


1 Answers

If you want to be sure the order of emissions is the same as the order in which you specified the source Observables you can use concat or concatMap operators.

The concat* operators subscribe to an Observable only after the previous Observable completes (it works with Promises as well, see http://reactivex.io/rxjs/class/es6/MiscJSDoc.js~ObservableInputDoc.html).

In you case it'd look like the following:

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

concat(printLog1, printLog23, printLog4);

... or with concatMap if the request for one Promise depends on the response from the previous Promise:

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

... or when the order doesn't matter you can use merge that subscribes to all Observables/Promises immediately and reemits their results as they arrive:

merge(printLog1, printLog23, printLog4);

Jan 2019: Updated for RxJS 6

like image 160
martin Avatar answered Oct 11 '22 14:10

martin