0

I'd like to issue a refresh token API call when an idle timeout ends in my app...

My incorrect code for doing so is:

idle.onIdleEnd.subscribe(() => {
            console.log('idle end reached');
            if (this.authStore.isAuthenticated()) {
                this.authService.refreshToken().subscribe(() => null);
            }

            this.activeModal.hide();
        });

However, this is for some reason exponentially triggering the refresh token, which is undesirable and ultimately creates a race condition with an invalid token being sent when a new one's been issued already (reads from local storage).

So when the idle timer fires once and i wiggle the mouse, refresh token fires once, however the 2nd time it fires twice, and the 3rd time it fires 4 times, how do I make it fire once per idle end?

RandomUs1r
  • 4,010
  • 1
  • 24
  • 44
  • so your problem is just with those refresh token requests, that console log is printed correctly? maybe you should flatMap the refresh token result instead of subscribing – Martin Adámek Oct 30 '18 at 23:18
  • where do you have this code? ngOnInit of some component? – Martin Adámek Oct 30 '18 at 23:21
  • @Martin yep I have a modal I call from app component to show the timeout timer that then triggers the idle end event, so the modal pops up and a user moves their mouse and then the idle end code fires. How would I use flatMap in my scenario? I'm new to RxJS. – RandomUs1r Oct 31 '18 at 15:03
  • And do you see that `console.log('idle end reached');` correctly or does it also fires exponentially? – Martin Adámek Oct 31 '18 at 15:08
  • sounds like your problem is that you subscribe to `idle.onIdleEnd` multiple times. i guess you should unsubscribe from it when you hide the modal window? – Martin Adámek Oct 31 '18 at 15:08

1 Answers1

2

Try unsubscribing from the observable when hiding the modal:

private subscription: Subscription;

this.subscription = idle.onIdleEnd.subscribe(() => {
    console.log('idle end reached');
    if (this.authStore.isAuthenticated()) {
        this.authService.refreshToken().subscribe();
    }

    this.activeModal.hide();
    this.subscription.unsubscribe();
});
Martin Adámek
  • 16,771
  • 5
  • 45
  • 64
  • Oh wow, the modal close doesn't clean up the subscription, good to know!, that worked, thanks man! – RandomUs1r Oct 31 '18 at 15:28
  • you need to unsubscribe everything that does not complete (http requests will complete, but DOM events and stuff that can occur repeatedly will not). another possibility is to use `take(1)` operator that will make sure the observable will complete after first emission. – Martin Adámek Oct 31 '18 at 15:30