skip to Main Content

I have 3 observables:

query$ = this.q$.pipe(tap(() => this.page$.next(0));
filter$ = this.f$.pipe(tap(() => this.page$.next(0));
page$ = new BehaviorSubject<number>(0);

combinetLatest({
  query: this.query$,
  filter: this.filter$,
  page: this.page$
})
.pipe(
  switchMap(({ query, filter, page }) => {
    ...
  })
);

I have to pass their values down the stream whenever any of them emit. However, using combineLatest results in at least two more redundant emits. I attempted to wire in distinctUntilChanged(), but this also produces one redundant emit at some point.

Please assist 🙁 or perhaps my entire approach/thinking is incorrect, and I should not change page$ as a side-effect of query$, filter$?

Update: In a sense, I don’t care about the "page" value, as it’s always 0 in the case of "query" or "filter" emissions. But I do care about "query" and "filter" values when "page" emits. So it seems that it becomes two separate observables?.. But I wanted to assign it to a component property in order to use it with the "async" pipe in the template, so with two different observables, I can’t…

2

Answers


  1. So, which of your observables do you prefer to emit immediately, and which ones should you just know their values? Take your main observable, and then add two others with the withLatestFrom operator just to accept data, but not emit your root source. As a result, your stream will only be called by one, but will accept two additional data along with it

    Login or Signup to reply.
  2. Maybe something like this would work:

    combineLatest({ query: this.q$, filter: this.f$ }).pipe(
      switchMap(({query, filter}) => this.page$.pipe(
        map((p, i) => i === 0 ? 0 : p)),
        map(page => ({query, filter, page}))
      ))
    );
    

    The idea is that your combineLatest starts with only the query and the filter, then switchMaps to the page. The second argument in the map operator indicates the "emission index" of the subscription to page$, which will start at 0, and increase each time page$ emits. So, we emit 0 when it’s the first emission and emit the value from page$ after that. Whenever either the filter$ or query$ emit, the switchMap will create a new subscription, which means the a new inner subscription to page$ is made meaning the index will start back at 0.

    You could tack on another switchMap to make your api call or just turn the second map into switchMap:

    combineLatest({ query: this.q$, filter: this.f$ }).pipe(
      switchMap(({query, filter}) => this.page$.pipe(
        map((p, i) => i === 0 ? 0 : p)),
        switchMap(page => this.callApi(query, filter, page))
      ))
    );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search