title: retryWhen operator with Hot Observable in RxJS
body: <p>The requirements is to get new value when auth token is expired and yet to keep it hot. Ideally in one observable variable (without separate Subject)</p>
  
  <p>Currently the code looks as follows:</p>
  
  <pre><code>constructor(private angularFireAuth: AngularFireAuth) {}
  
  private getAuthTokenResult(): Observable&lt;firebase.auth.IdTokenResult&gt; {
    return this.angularFireAuth.authState.pipe(
      switchMap(user =&gt; {
        if (user) {
          return from(user.getIdTokenResult(true));
        } else {
          return of(null);
        }
      })
    );
  }
  
  public authToken$: Observable&lt;string&gt; = this.getAuthTokenResult().pipe(
    map((result: firebase.auth.IdTokenResult) =&gt; {
      if (new Date() &gt;= new Date(result.expirationTime)) {
        throw new Error('Token Expired');
      } else {
        return result.token;
      }
    }),
    retryWhen(errors =&gt;
      errors.pipe(
        tap(() =&gt; console.log('Token Expired. Getting New One...')),
        delay(100),
        take(3)
      )
    ),
    shareReplay(1)
  ) as ConnectableObservable&lt;string&gt;;
  </code></pre>
  
  <p>But it doesn't do the job, after auth token is expired - it the new one is not received.</p>
  
  <p>This is how the dependant service method looks like</p>
  
  <pre><code>addProduct(
    data: MerchantProductPartial
  ): Observable&lt;MerchantProduct&gt; {
    return this.authService.authToken$.pipe(
      switchMap(token =&gt; {
        // console.log('_addProduct', token);
        if (token) {
          const endpoint = ``;
          const httpOptions = {
            headers: new HttpHeaders({
              'Authorization': `Bearer ${token}`,
            })
          };
          return this.http.post(endpoint, data, httpOptions);
        }
        else {
          throw new Error('Authorization Token not provided.');
        }
      })
    );
  }
  </code></pre>
  
  <p>and the method execution as follows</p>
  
  <pre><code>this.merchantService.addProduct({
        name: 'New Test Product'
      }).pipe(take(1)).subscribe(res =&gt; console.log('res:', res), err =&gt; console.log('err:', err))
  </code></pre>
  
  <p><strong>SOLUTION</strong>:</p>
  
  <p>If anyone concerns about the solution - it simpler then I thought. Just need to use a different method <a href="https://firebase.google.com/docs/reference/js/firebase.User#getIdToken" rel="nofollow noreferrer">https://firebase.google.com/docs/reference/js/firebase.User#getIdToken</a> which automatically updates invalid tokens... Just don't forceRefresh it...</p>
  
  <pre><code>public authToken$: Observable&lt;string&gt; = this.angularFireAuth.authState.pipe(
    switchMap(user: firebase.User =&gt; {
      if (user) {
        return from(user.getIdToken());
      } else {
        return of(null);
      }
    })
  );
  </code></pre>