Search code examples
angularrxjs

is there a way create counter with timeout() operator which is being used to timeout a observable?


need to show a count down counter in UI for 10 second while waiting for below observable to emit. if below observable does not emit with in 10 seconds its timed out. can the UI counter also be clubbed in the below code?

 this.authSubscription =     onauthReceived$.pipe(timeout({ first: 10 * 1000 })).subscribe({
            next: () => {
                console.log('do something)
            },
            error: err => {
                console.log('timed out before 7 seconds: ', err);
            },
            complete: () => {
                
                             console.log('complete)             
            }
        });

I have a different counter function but want to know if it can be clubbed so while waiting for observable to emit counter can be shown in UI.


Solution

  • You can use the combineLatest operator to combine two or more streams:

    @Component(...)
    export class App {
      authenticated$ = new Subject<string>();
    
      viewModel$ = combineLatest({
        authenticated: this.authenticated$.pipe(
          timeout(10 * 1000),
          startWith(null)
        ),
        countdown: timer(0, 1000).pipe(
          map((count) => 10 - count),
          takeUntil(this.authenticated$)
        ),
      }).pipe(
        catchError(() =>
          of({
            authenticated: 'you were too late!',
            countdown: 0,
          })
        )
      );
    }
    

    In my example viewModel$ is an observable stream that emits an object that has a countdown and an authenticated property, allowing you to show the value of viewModel.countdown in your template:

    <button (click)="authenticated$.next('authenticated!')">authenticate</button>
    <pre>{{viewModel$ | async | json}}</pre>
    

    Here's a working example: https://stackblitz.com/edit/stackblitz-starters-jwyazf?file=src%2Fmain.ts