Let’s say you have a web application which deals with “content”, so works much like a web site: one-page per item, and when you click a link, just load the next page. It’s very old fashioned, but it works the way the web works, and works well. Users are encouraged to have more than one page open at a time, and this works well, as it does for web sites.
Just like any other web application, you have some state on the server which is reflected on those pages, for example, which user is logged in, how many tasks they have to complete, how many items in their basket, and so on.
When you have multiple pages open, you can do something which changes that state, but it’s only reflected in the page which is returned in response. All the other windows show the old state. Wouldn’t it be nice to have a lightweight way of broadcasting state changes between the pages so they could update their state too?
Proper messaging systems
There are ways you can communicate between windows, for example, calling a user defined function on a
window object, or using the new postMessage API (intended for cross-domain messaging). But for both of these, you need to have a reference to the other windows, so you can’t just broadcast to every window.
You can also use something like long polling or WebSockets to push events from the server, perhaps using Shared Web Workers to avoid opening one connection per page, but this feels like using a very large hammer to crack a very small nut.
Abusing localStorage for messaging
Whenever you change a bit of data in
“storage” event is sent to every other window showing a page from the same hostname. Which is exactly what we want.
Here’s a proof-of-concept demo: localStorage inter-window messaging demo (opens in new window)
Open it multiple times, and then change the contents of the checkbox. It works beautifully in Firefox, Safari, Chrome, and even Internet Explorer.
So, the mechanism would look like:
- When the page is initially loaded, write an item to
window.localStoragewith the current state.
- Listen to events from other windows, and update the state when received.
- Because the spec doesn’t guarantee swift delivery, and the user may navigate between pages, listen on the
windowobject for the “focus” event and read the current state from
Is this sensible?
I have a couple of questions:
- Are there any problems with this scheme?
- Am I missing a really obvious better way of doing this?
Feedback gratefully received. Thank you!
UPDATE The consensus seems to be that this is not entirely crazy, and there isn’t a better way. And Martin Kleppmann points out:
@bensummers Well, with the storage event it really is a kind of message passing API (that also happens to persist the last message sent).
— Martin Kleppmann (@martinkl) March 9, 2013
COMMENTSblog comments powered by Disqus