A Simple Side‑Effect‑Free Same‑Origin Cross‑Page Data Synchronization Solution
This article explains how to use localStorage, sessionStorage, and the storage event to achieve reliable, side‑effect‑free data synchronization between same‑origin web pages, providing a practical implementation with JavaScript code and detailed design considerations.
Background
The problem originated when a user opened two online editing pages of the pageOffice tool simultaneously; the second page could modify the document while the first page was still active, leading to file tampering.
Investigation revealed that pageOffice runs as an independent service with only a single callback mechanism, making it impossible to detect or prevent a second instance from opening.
Exploration
Since the tool cannot be directly controlled, the focus shifted to communication between the two browser pages. A common approach is to use a state flag (e.g., ifOpen ) stored in a variable, but the flag must be shared across pages.
Local storage ( localStorage ) and session storage ( sessionStorage ) were examined. localStorage persists across tabs of the same origin, while sessionStorage is scoped to a single window and clears on close.
localStorage: persistent, same‑origin read/write, not cleared automatically.
sessionStorage: temporary, same‑origin and same‑window only, cleared when the window closes.
The persistence of localStorage can cause side effects when a page is closed while pageOffice remains open, leaving stale flags that prevent future openings.
Design
Two solution ideas were considered:
Store an array of open page IDs in localStorage and remove the ID on page unload. This fails because the beforeunload event also fires on page refresh, causing unintended deletions.
Leverage the storage event, which fires in other same‑origin tabs when localStorage changes. This event can be used to propagate state without relying on unload detection.
By combining sessionStorage (which clears automatically on window close) with the storage event, a bridge can be built where localStorage acts only as a transport channel.
Implementation
The core idea is:
When data changes, write it to sessionStorage for the current page.
Trigger a change in localStorage (using a specific key) to notify other pages.
Other pages listen to the storage event, read the new value, and update their own sessionStorage .
Immediately remove the temporary key from localStorage to avoid side effects.
Key functions:
// Trigger event when data needs to be synchronized
function setSessionStorage(payload) {
const data = JSON.stringify(payload);
// Store in current page
sessionStorage.setItem('setSessionStorage', data);
// Notify other pages via localStorage
localStorage.setItem('setSessionStorage', data);
// Clean up the transport key
localStorage.removeItem('setSessionStorage');
}Listener for the storage event:
function storageChange(e) {
const ifNull = e.newValue === null && e.newValue === 'null';
// Sync data from other pages
if (e.key === 'setSessionStorage' && !ifNull) {
sessionStorage.setItem('setSessionStorage', e.newValue);
}
// When a new page loads, request current session data
if (e.key === 'getSessionStorage' && !ifNull) {
const currentSessionStorage = sessionStorage.getItem('setSessionStorage');
localStorage.setItem('setSessionStorage', currentSessionStorage);
localStorage.removeItem('setSessionStorage');
}
}Initialization routine that registers the listener and triggers an initial sync:
function init() {
// Listen for storage changes
window.addEventListener('storage', storageChange);
// Ask other tabs for their session data
localStorage.setItem('getSessionStorage', 'any');
localStorage.removeItem('getSessionStorage');
}After calling init() , any page can retrieve the synchronized data with:
const currentSessionStorage = sessionStorage.getItem('setSessionStorage');This approach provides a simple, side‑effect‑free method for same‑origin cross‑page data synchronization.
Conclusion
The solution uses localStorage solely as a transient bridge, while the actual state lives in sessionStorage , ensuring that stale data does not persist after a page is closed. The implementation is lightweight, requires only standard Web APIs, and avoids the pitfalls of unload events.
政采云技术
ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.