I have a service that store items in the session storage with an expiry date. When i retrieve an item, if the expiry date is over, the service return null value :
The method to save items :
private saveSessionData<T>(key: string, value: T) {
const now = new Date();
const item = {
value: value,
expiry: now.getTime() + 15 * 60000 // 15 minutes from now
}
sessionStorage.setItem(key, JSON.stringify(item));
}
The method to retrieve items :
private getSessionData<T>(key: string): T | null {
const itemStr = sessionStorage.getItem(key);
if(!itemStr) return null;
const item = JSON.parse(itemStr);
const now = new Date();
if (now.getTime() > item.expiry) {
sessionStorage.removeItem(key);
return null;
}
return item.value;
}
In my controller, I access one of those value by putting them on an Observable like :
const value$ = of(this.storageService.getSessionData<string>('value'))
.pipe(
catchError(err => {
console.log('The session is expired');
// ... open a modal and route the user to the home
return err;
})
);
And then i display it in my view with :
{{(value$ | async)}}
The thing I want as soon as my Stored data is expired, is to open a Modal and route the user to an other page (It is what i did in the catchError()
.
The problem is that when my data actually expire, in the console I have multiple logs meaning i entered multiple times in my catchError()
which is a problem since my openModal function is not idempotent (so it open multiple times leading to a poor user experience) :
console.log :
The session is expired
The session is expired
The session is expired
The session is expired
The session is expired
How can i change this to actually call the error function only once ?
I tried to use throws new Error('session expired')
instead of the return null;
in my retrieve data function and put a try() catch() block in my controller, but it ended the same.
Does anyone got an idea on how catch my error only once ?
If you have multiple value$ | async
in the template, you will end up with multiple subscriptions!!!
You can apply the share()
operator to ensure only a single subscription is used:
const value$ = of(this.storageService.getSessionData<string>('value')).pipe(
share(),
catchError(err => {
console.log('The session is expired');
})
);