25

I hear HTML5 has window.postMessage(), but it seems to require having a handle on the window (or tab, throughout this question) you're posting the message to. What if I want to broadcast to all open windows? Is this possible?

(What I'm trying to do is warn other windows without any server round-trips when a user does something in one window that affects the others, so that they can update their content. However, while some windows may be opened from existing ones--allowing me to intercept and store references to them--some fresh windows may be opened manually by the user and then a bookmark selected or URL typed in. In this case there doesn't seem to be a way to intercept and store references.)

Kev
  • 15,899
  • 15
  • 79
  • 112
  • Depending on your use-case, Comet (or other similar "HyBi" mecanism) might be a better choice; for example if you want the notification to be cross-browser (i.e. the user has opened IE and Firefox, it makes a change in IE, and expects Firefox to be notified). Also, I don't know exactly how all browsers work (there might be configurable options that changes their default behavior, such as the -no-remote command line argument for Firefox) but even for the same browser, all windows might not be able to communicate without Comet-style/server-driven communications. – Thomas Broyer Jul 09 '09 at 08:43
  • Thanks, but I already have a server-side fallback...I just wanted it to feel a bit snappier by being more efficient when possible. – Kev Jul 10 '09 at 18:06

2 Answers2

26

I wrote a library to do just this: intercom.js (for the same reasons you outlined).

We're currently using it to broadcast notifications to all windows, so only one window needs to maintain a socket connection to the server. As some others suggested, it uses the localStorage API.

Usage is really simple:

var intercom = Intercom.getInstance();

$('a').on('click', function() {
     intercom.emit('notice', {message: 'Something just happened!');
});

To catch the message,

intercom.on('notice', function(notice) {
    console.log(notice.message);
});

The interface is designed to mimic socket.io.

brianreavis
  • 11,562
  • 3
  • 43
  • 50
  • This looks pretty cool. Dumb question, but does this work between different domains? I wouldn't expect the `Storage` events to work across windows in different domains since they'll have their own `localStorage`. I know I could test it out, but I just thought I'd ask – Ian Jun 28 '13 at 03:52
  • 1
    It has to be on the same domain :/ If you *really* wanted to get crazy you could probably get crazy with iframes and postMessage + Intercom to get something cross-domain working. – brianreavis Jun 28 '13 at 22:33
  • Would this work effectively as a fallback for shared web workers? I'm trying to set up a webworker whose data is shared between tabs, not unlike your binding for socket.io except it's communicating with the worker instead of a server. If the tab with the worker is closed it should be relaunched on a different tab. – Holy Crap Jul 01 '13 at 02:43
  • I don't see why that wouldn't be possible :) – brianreavis Jul 03 '13 at 05:29
  • two disadvantages - doesn't work for offline webapps, may achieve high delays – Lapsio Nov 21 '13 at 09:31
  • @Lapsio You can also use `postMessage` to send messages between offline web apps on different domains. [sysend.js](https://github.com/jcubic/sysend.js) does this using iframes, for example. – Anderson Green Apr 08 '22 at 15:35
21

IMO this is not possible using the postMessage. How about using sessionStoragelocalStorage? Writing to it should generate a storage event that should be propagated to all windows sharing the same session storage.

Elmo
  • 6,409
  • 16
  • 72
  • 140
Rafael
  • 18,349
  • 5
  • 58
  • 67
  • Or cookies (as long as they're in the same domain) – Chetan S Jul 08 '09 at 20:37
  • 3
    cookies could also be a solution, but the advantage of storage is that it generates events when performing operations on it. When using cookies you would have to check every X seconds (setInterval) for new cookies and another problem would be when to remove the cookie. – Rafael Jul 08 '09 at 20:48
  • 1
    The thing is, as I understand the spec ( http://www.w3.org/TR/webstorage/#the-storage-event ) correctly, the event should be fired in both cases (sessionStorage and localStorage). If Firefox doesn't fire the event, IMO this is a bug. – Rafael Jul 15 '09 at 19:31
  • 3
    Nope, this it isn't a bug. According to the specs each document has it's own sessionStorage object, only the localStorage object is shared over all documents of the same origin. Therefore a storage event fired by the sessionStorage of Window A won't be heard by listeners, who are observing the sessionStorage of window B. – Torben Jan 12 '12 at 18:04
  • I also use local storage for this purpose. keep in mind that local storage fires even on removal of key. so its best to check event.newvalue since its null on removal. – CodeToad Nov 27 '14 at 15:16