rxjs: show loading spinner only if it takes > 1s to load

758 views Asked by At

I have a Subject refreshData$ that triggers data refetch:

const data$ = refreshData$.pipe(
    switchMap(() => dataService.load())
);

I need to show loading indicator only if load take more than 1 second. If data arrives in under 1s - do not show the spinner.

Found very good answer here, but it recreates the observables on every refresh. And I want to reuse them. I have started with the following, but it it only works one time. I guess takeUntil has to be replaced with something else here.

const showSpinner$ = merge(
    refreshData$.pipe(
        delay(1000),
        mapTo(true),
        takeUntil(data$)    // FIXME: only shows loading once
    ),
    data$.pipe(
        timeInterval(),
        mapTo(false)
    )
);

----
to be used in template as:
<loading-spinner *ngIf="showSpinner|async"></loading-spinner>
2

There are 2 answers

0
Mrk Sef On BEST ANSWER

I would create a disposable stream, so that if takeUntil() terminates it early, your outer observable (showSpinner$) continues.

const showSpinner$ = merge(
  refreshData$.pipe(
    switchMap(_ => timer(1000).pipe(
      mapTo(true),
      takeUntil(data$)
    ))
  ),
  data$.pipe(
    mapTo(false)
  )
);
0
MoxxiManagarm On

Did you try something like this?

const showSpinner$ = refreshData$.pipe(
  switchMap(() => timer(1000)),
  mapTo(true),
  takeUntil(data$),
  endWith(false),
);