Here is an alternate approach that works within the same window by patching sessionStorage.setItem
. It is a strong approach, because it leverages the Browser's built-in event mechanism...no need to maintain your own state manually using an RxJS Subject.
Patch the sessionStorage.setItem
function to manually generate a "storage" event within this window:
const origSetItem = window.sessionStorage.setItem;
window.sessionStorage.setItem = function setItem(key, value) {
// Retrieve old value before we store the new one
let oldValue = window.sessionStorage.getItem(key);
// Store in SessionStorage
const result = origSetItem.apply(this, arguments);
// Manually fire a "storage" event so this window is alerted. On its own,
// sessionStorage.setItem() only fires a "storage" event for other tabs.
const e = new StorageEvent('storage', {
storageArea: window.sessionStorage,
key,
oldValue,
newValue: value,
url: window.location.href,
});
window.dispatchEvent(e);
return result;
}
Provide a reusable mechanism for observing an entry in SessionStorage:
import { fromEvent, Observable } from 'rxjs';
import { filter } from 'rxjs/operators';
export const sessionStorageUtils = {
observe,
};
/* Observe a specific entry in SessionStorage */
function observe(key: string): Observable<StorageEvent> {
// Observe the window for "storage" events
return fromEvent<StorageEvent>(window, 'storage')
.pipe(
filter((e: StorageEvent) => e.key === key),
filter((e: StorageEvent) => e.newValue !== e.oldValue),
);
}
Example Usage:
import { sessionStorageUtils } from './session-storage-utils';
// Don't forget to unsubscribe from this Observable OnDestroy
sessionStorageUtils.observe('testKey')
.subscribe((data) => {
console.log(data);
});