If I understand this correctly, the `BroadcastChannel` API solves a similar purpose.<p><a href="https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API" rel="nofollow">https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_C...</a>
The subscribe() implementation seems suboptimal in the case where there are many different topics:<p><pre><code> subscribe(topic, callback) {
if (this.listeners[topic] == undefined) {
// Not yet any listener for this topic
this.listeners[topic] = [];
window.addEventListener('storage', (e) => {
const dataKey = topic + "_data";
if (e.key === dataKey) {
const data = JSON.parse(e.newValue)[0];
this.listeners[topic].forEach((v, k) => {
v(data);
});
}
}, false);
}
this.listeners[topic].push(callback)
}
</code></pre>
This installs a handler for every single topic, and every time a message is published, the handlers for all topics are called, even though at most one is interested in the change. A more efficient implementation would install a single handler, e.g. (untested):<p><pre><code> window.addEventListener('storage', (e) => {
if (e.key.endsWith('_data')) {
const topic = e.key.substring(0, e.key.length - 5);
const data = JSON.parse(e.newValue)[0];
this.listeners[topic]?.forEach(v => v(data));
}
}, false);</code></pre>
I built a ComfyUi node that let you run a little paint program in another tab. (Sorry about the lack of updates if you use it. I intend to get back to it)<p>Negotiating the communication between tabs was by far the hardest part. In the end I ended up using local storage for signaling to establish a dedicated messsageport channel.<p>It was such a fight to make something that re-established the connection when either page reloaded.<p>There are still some connection issues that I haven't been able to resolve. It seems some browsers on some systems reject messages between tabs if they were loaded hours apart.<p>It might be worth benchmarking a pure local storage fallback, but I'm guessing it would suffer with high traffic.<p>A generalised implementation that allowed switching multiple paint programs and multiple ComfyUi pages would be ideal. A PubSub might be the way to go.<p>There's also the issue of other parts of the app also using local storage. Need to not step on toes.
I remember implementing the same thing in our framework like a decade ago, but eventually taking it out. We wanted to use it for caching data between tabs, so as not to hit the server again per tab:<p><a href="https://github.com/Qbix/Platform/blob/main/platform/plugins/Q/web/js/Q/Frames.js" rel="nofollow">https://github.com/Qbix/Platform/blob/main/platform/plugins/...</a><p>It had the concept of a “main frame” that they would route all requests to the server through.<p>I remember now — I did it not so much for tabs as for our solution of having tons of little iframes on a page: <a href="https://qbix.com/ecosystem" rel="nofollow">https://qbix.com/ecosystem</a>
The audio demo makes me think of Bandcamp which will pause music that you're playing if another Bandcamp tab starts playing a song separately. Must be a similar mechanism under the hood
I love it, the code is so simple: <a href="https://github.com/simonfrey/tabsub/blob/master/tabsub.v1.js" rel="nofollow">https://github.com/simonfrey/tabsub/blob/master/tabsub.v1.js</a>
Isn't this a security hole waiting to be exploited?<p>How does the browser handle access control to the local storage, especially offline when they aren't loaded from the same site?<p>[Yes, I really don't know. Yes, I'm asking. Not everyone is a web dev.]
Very cool, I love seeing pubsubs in the wild. We built an ssh based pubsub that we have been using in production for awhile now: <a href="https://pipe.pico.sh/" rel="nofollow">https://pipe.pico.sh/</a>