26

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.)

2
  • 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. Commented Jul 9, 2009 at 8: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. Commented Jul 10, 2009 at 18:06

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

6 Comments

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
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.
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.
I don't see why that wouldn't be possible :)
two disadvantages - doesn't work for offline webapps, may achieve high delays
|
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.

5 Comments

Or cookies (as long as they're in the same domain)
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.
The thing is, as I understand the spec ( 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.
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.
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.
6

Assuming you don't need to broadcast a message to other websites (just your own), BroadcastChannel is made for this purpose.

const channel = new BroadcastChannel('myChannel');
channel.postMessage('myMessage');
channel.addEventListener('message', event => {
    console.log('Received message from other document:', event.data, event);
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.