Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hasty forkjoin alternative rxjs for observable chaining?

I have 5 different API calls to make, and they all are chained right now in forkJoin. My new requirement is the subscribe should fire anytime any new observable solves.

Is there any operator or any other trick in rxjs where I can keep the chaining but, it should fire each time any observable solves?

forkJoin(
        this.myService.api1(),
        this.myService.api2(),
        this.myService.api3(),
        this.myService.api4(),
        this.myService.api5()
    )
        .subscribe(
            ([r1,r2,r3,r4,r5]) => { ... do something })
like image 375
Aijaz Avatar asked Jan 08 '20 16:01

Aijaz


People also ask

Is RxJS forkJoin deprecated?

forkJoin Improvements This is one of my favorites. The forkJoin observable now takes a dictionary of sources: Moreover, there is one deprecation — forkJoin(a, b, c, d) should no longer be used; Instead, pass an array such as forkJoin([a, b, c, d]) .

Does forkJoin complete?

If no input observables are provided (e.g. an empty array is passed), then the resulting stream will complete immediately. forkJoin will wait for all passed observables to emit and complete and then it will emit an array or an object with last values from corresponding observables.

Does forkJoin run in parallel?

forkJoin is one of the most popular combination operators due to its similar behavior to Promise. all but for observables. forkJoin accepts a variable number of observables and subscribes to them in parallel.

What is forkJoin RxJS?

The RxJS forkJoin() operator is a join operator that accepts an Array of ObservableInput or a dictionary Object of ObservableInput and returns an Observableand then waits for the Observables to complete and then combine last values they emitted.


1 Answers

You can use combineLatest to emit the latest value from each source observable. It won't emit until each source observable emits at least once, so you can use startWith to provide a starting value:

combineLatest(
        this.myService.api1().pipe(startWith(null)),
        this.myService.api2().pipe(startWith(null)),
        this.myService.api3().pipe(startWith(null)),
        this.myService.api4().pipe(startWith(null)),
        this.myService.api5().pipe(startWith(null))
    )
        .subscribe(
            ([r1,r2,r3,r4,r5]) => { ... do something })

The initial output will be [null, null, null, null, null]. When each observable emits, it will replace the corresponding null value in the array.

If you want to ignore the initial emission, you can use skip(1).

const sourceOne = of('Hello').pipe(delay(1000));
const sourceTwo = of('World!').pipe(delay(2000));
const sourceThree = of('Goodbye').pipe(delay(3000));
const sourceFour = of('World!').pipe(delay(4000));

//wait until all observables have emitted a value then emit all as an array
const example = combineLatest(
  sourceOne.pipe(startWith(null)),
  sourceTwo.pipe(startWith(null)),
  sourceThree.pipe(startWith(null)),
  sourceFour.pipe(startWith(null))
)
.pipe(skip(1));

//output:
//["Hello", null, null, null]
//["Hello", "World!", null null]
//["Hello", "World!", "Goodbye", null]
//["Hello", "World!", "Goodbye", "World!"]
//Complete
const subscribe = example.subscribe(val => console.log(val), null, () => console.log('Complete'));

And here's a StackBlitz to try it out.

like image 99
Alex K Avatar answered Sep 24 '22 21:09

Alex K