简体   繁体   中英

RxJS - Conditionally add observable in a pipe

So i have a function like below

showLoader = () => <T>(source: Observable<T>) => {
  LoaderService.loadPage.next(true);
  return source.pipe(
    finalize(() => {
        LoaderService.loadPage.next(false);
    })
  );
};

And then i use it while making HTTP calls like below

return this.http.get(url).pipe(showLoader())

But let's say i encounter a scenario where i need the loader or any observable for that matter based on a condition; something like below

const loader : boolean = false
return this.http.get(url).pipe(concat(...), loader ? showLoader() : of(values))

I tried using the iif operator like below

const loader : boolean = false
    return this.http.get(url).pipe(concat(...), mergeMap(v => iif(() => loader, showLoader(), of(v))))

and got the following error

TS2345: Argument of type '(source: Observable) => Observable' is not assignable to parameter of type 'SubscribableOrPromise<{}>'.

Can someone hep me understand where i am going wrong and how to rectify the same

you could do it like this:

showLoader = (show: boolean = true) => <T>(source: Observable<T>) => {
  if (!show) { // just go straight to source
    return source;
  }

  return defer(() => { // defer makes sure you don't show the loader till actually subscribed
    LoaderService.loadPage.next(true);
    return source.pipe(
      finalize(() => {
        LoaderService.loadPage.next(false);
      })
    )
  })
};

use:

return this.http.get(url).pipe(showLoader(false))

but the way you seem to be statically accessing LoaderService reeks of design issues and bugs in your future. FYI.

I would suggest something like following:

const startWithTap = (callback: () => void) =>
  <T>(source: Observable<T>) => of({}).pipe(
    startWith(callback),
    switchMap(() => source)
  );

const showLoader = () => <T>(source: Observable<T>) => concat(
  iif(
    () => loader,
    source.pipe(
      startWithTap(() => LoaderService.loadPage.next(true)),
      finalize(() => {
        LoaderService.loadPage.next(false);
      })
    ),
    EMPTY
  ), source);

return this.http.get(url).pipe(
  showLoader()
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM