Web Dev Quick Tip: Cross Tab Communication
by Michael on (Updated on )
Back
The other day, I was given an interesting requirement for a webapp I work on: allow the user to open multiple tabs simultaneously. Any data changes in one tab should instantly reflect in the other. Additionally, if the user logged out of the app in one tab, they should also be logged out in the other.

There are several ways to implement this functionality, and I will highlight three.

1) Broadcast Channel API

Although it may be missing from IE/Edge/Safari, the Broadcast Channel API is an HTML spec compliant method of communicating between tabs of the same origin (same domain). The API enables us to send any serializable data, which means our messages can be simple strings or even certain complex objects.

    //Create a broadcast channel with a unique name so other tabs can find it
    const channel = new BroadcastChannel('myChannelName');
    //listen for messages from other tabs.
    channel.addEventListener('message', (event) => {
        //event.data will contain the message from the other tab - process away!
        console.log(event.data);//would log {value: 'Hello, world'}
    });
   
    //...somewhere else in the application, we can send a message
    channel.postMessage({value: 'Hello, world'});
});

2) Storage Polling

If you need to support multiple older browsers, another technique for cross tab communication is to poll localstorage. The idea is that every tab checks the storage regularly for new messages. This method isn't as efficient as the Broadcast Channel, but it has much better browser support.

    let lastProcessedMessage;//keep track of the last processed message
    setInterval(() => {//poll for new messages regularly
        let message = localStorage.getItem('tabMessage');//check some know location in localStorage
        if(message) {
            message = JSON.parse(message);
            if(message.id != lastProcessedMessage) {//only process new messages
                lastProcessedMessage = message.id;
                console.log(message);//new message to process. Logs {id: 1, value: "Hello, world"}
            }
        }
    }, 1000);
   
    //...somewhere else in the application, we can send a message
   localStorage.setItem('tabMessage', JSON.stringify({id: 1, value: 'Hello, world'}));
});

2) Both! (Broadcast Channel API Polyfill)

If you need to support older browsers, but you don't want to do the heavy lifting of managing messages yourself, you can find a polyfill for it here. This polyfill will either use the native Broadcast Channel API, or it will fall back to storage polling if it's not available.