Skip to content

Instantly share code, notes, and snippets.

@jhthorsen
Created September 8, 2018 11:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhthorsen/604c3de1c2cd0ff2c34133192bdeedbd to your computer and use it in GitHub Desktop.
Save jhthorsen/604c3de1c2cd0ff2c34133192bdeedbd to your computer and use it in GitHub Desktop.
(function(w) {
/*
* Allow multiple clients share the same connection, but send/receive data on a topic they want
*
* var ws = WebSocketChannel("wss://example.com/mux", "testTopic");
* var ws = WebSocketChannel("wss://example.com/mux", {topic: "..", protocols: ...});
* var ws = WebSocketChannel({url: "wss://example.com/mux", topic: "..", protocols: ...});
* ws.onopen = function(e) { this.send({some: data}) };
*/
w.WebSocketChannel = function(url, params) {
if (arguments.length == 1) url = params.url;
if (typeof params != "object") params = {topic: params};
var mux = ensureMux(this, url, params);
// Allow us to change the topic later on
this.topic = params.topic;
[
"binaryType",
"bufferedAmount",
"extensions",
"protocol",
"readyState",
"url"
].forEach(attr => {
// Read actual values from the WebSocket
Object.defineProperty(this, attr, {
get: function() { return mux.ws[attr] },
set: function(v) { this.debug && console.trace("Cannot set WebSocketChannel." + attr + "=" + v) }
});
});
this.close = function() {
// Only close if this is the last connection
if (mux.instances.length <= 1) mux.ws.close.apply(mux.ws, arguments);
mux.instances = mux.instances.filter(instance => { return instance != this; });
};
this.send = function(data) {
mux.ws.send(JSON.stringify([this.topic, data]));
};
};
var pool = w.WebSocketChannel.WebSocketPool = {};
var ensureMux = function(obj, url, params) {
var key = [].concat(params.protocols || "undefined").concat(url).join(":");
var mux = pool[key] || (pool[key] = {instances: []});
// Add obj to the list of listeners/instances
mux.instances.push(obj);
if (mux.ws) return mux;
// Set up the initial WebSocket connection
mux.ws = new WebSocket(url, params.protocols);
["onclose", "onerror", "onopen"].forEach(attr => {
// Proxy events to the instances
mux.ws[attr] = function(e) {
mux.instances.forEach(function(instance) {
if (instance[attr]) instance[attr](e);
});
};
// Cleanup
if (attr == "onclose") delete pool[key];
});
mux.ws.onmessage = function(e) {
var data = JSON.parse(e.data);
e.data = data[1];
mux.instances.forEach(function(instance) {
if (instance.onmessage && instance.topic == data[0]) instance.onmessage(e);
});
};
return mux;
};
})(window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment