skip to Main Content

How to return different values from the same observable without multiple calls? I intend to subscribe just one time the firstObs$, but return the values and sumFromValues.

combineLatest([
            this.firstObs$,
            this.firstObs$.pipe(
                switchMap(someOperation => {
                       return this.observableSumOperation(someOperation.first, someOperation.second)
                })
            ),
          
            this.anotherObservable$,
        ])
          .subscribe(([values, sumFromValues, anotherValues]) => {
            }

2

Answers


  1. As you’ve noticed, when you include the same source observable inside of combineLatest, the "combinelatest observable" will emit multiple times. Generally this is not desirable.

    I can think of two solutions for this:

    1. use debounceTime(0) to suppress emissions that occur in the same event loop:
    combineLatest([
      firstObs$,
      firstObs$.pipe(map(({first, second}) => first + second)),
      anotherObservable$,
    ])
    .pipe(debounceTime(0));
    
    1. only include each source once inside of combineLatest and use map to build a new array/object that includes your derived value:
    combineLatest([
      firstObs$,
      anotherObservable$,
    ])
    .pipe(
      map(([values, anotherValues]) => [
        values,
        values.first + values.second,
        anotherValues
      ])
    );
    

    Here is a StackBlitz that shows the problem and solutions.

    Login or Signup to reply.
  2. Since you didn’t specify what anotherObservable contains and how it behaves its hard to say how to best combine the values. But one idea is to split the combination of observables into two steps:

    1. Map the firstObs$ result together with observableSumOperation
    const calculated$ = this.firstObs$.pipe(
          mergeMap((values) =>
            this.observableSumOperation(values.first, values.second).pipe(
              map((sum) => ({ ...values, sum })),
            ),
          ),
        )
    
    1. Combine calculated$with anotherObservable$:
     combineLatest([calculated$, this.anotherObservable$]).subscribe(
          ([values, anotherValues]) => {
            const { first, second, sum } = values
          },
        )
    

    Note that combineLatest will only fire as soon as every observable emits at least once. So if anotherObservable$ does not emit a value, you will not enter the subscribe method

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search