Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJS finalize(): pass the last emitted value to the callback

In my Angular service, I've got a loading prop which I set true as a first thing done in the method fetching data. I want to set loading to false after the data is downloaded. I was doing it in finalize():

public fetch: (type: myType, page?: number) => Observable<any> = (
type: myType,
page: number = 1
  ) => {
    return this.serviceFor(type)
      .fetchList(page, this.queryParams)
      .pipe(
        map(({ data, meta }) => {
          return ({ collectionName: type, collection: data, meta })
        }),
        finalize(() => {
          this.loading.next(false)
        })
      );
  };

Now, I have three loading props, each one corresponding to a different type. I would like to pass type(collectionName) to finalize. Since finalize() doesn't take any aguments, it there any other way to take last emitted value and do something with it when stream is done?

finalize((collectionName) => {
      switch (collectionName)
         ...
    })

Linked topic: https://github.com/ReactiveX/rxjs/issues/4803

EDIT: Question is answered in the comment by kruschid.

like image 264
Aleks Grunwald Avatar asked Oct 23 '25 14:10

Aleks Grunwald


2 Answers

function finalizeWithValue<T>(callback: (value: T) => void) {
  return (source: Observable<T>) => defer(() => {
    let lastValue: T;
    return source.pipe(
      tap(value => lastValue = value),
      finalize(() => callback(lastValue)),
    )
  })
}

Source

Edit: I find myself doing this these days

source$.pipe(
  switchMap(value =>
    of(value).pipe(
      concatWith(NEVER),
      finalize(() => {
        cleanup(value)
      })
    )
  )
)

Each time source$ emits, the previous emission will be cleaned up. And when unsubscribed, the last emission is also cleaned up.

like image 63
Sarsaparilla Avatar answered Oct 26 '25 14:10

Sarsaparilla


I would use a tap operator to do whatever you need with the emmited value, and keep the finalize just for setting loading to false. You might need to check last operator also. A combination of them should be enough.

like image 21
Manuel Fabri Avatar answered Oct 26 '25 13:10

Manuel Fabri