Skip to content

Instantly share code, notes, and snippets.

@jonasraoni
Created March 30, 2019 19:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonasraoni/ed55033a7f9bb3da7cb84c0ebded14fc to your computer and use it in GitHub Desktop.
Save jonasraoni/ed55033a7f9bb3da7cb84c0ebded14fc to your computer and use it in GitHub Desktop.
Class to handle SignalR subscriptions
//+ Jonas Raoni Soares Silva
//@ http://raoni.org
const signalR = require('@aspnet/signalR');
export default class Hub {
constructor (url, autoReloadTimeout = 1000) {
Object.assign(this, {
url,
autoReloadTimeout,
connection: null,
isStarted: false,
closeGracefully: false,
eventHandlerMap: new Map()
});
}
on (event, handler) {
let eventHandler = this.eventHandlerMap.get(event);
if (!eventHandler) {
eventHandler = {
subscriptionSet: new Set(),
handler: (...args) => {
try {
for (const handler of eventHandler.subscriptionSet) {
handler(...args);
}
} catch (e) {
console.info(e);
}
}
};
this.eventHandlerMap.set(event, eventHandler);
if (this.connection) {
this.connection.on(event, eventHandler.handler);
}
}
const subscriptionSet = eventHandler.subscriptionSet;
subscriptionSet.add(handler);
return this;
}
off (event, handler) {
if (event === undefined) {
if (this.connection) {
for (const [event, eventHandler] of this.eventHandlerMap) {
this.connection.off(event, eventHandler.handler);
}
}
this.eventHandlerMap = new Map();
} else {
let eventHandler = this.eventHandlerMap.get(event);
if (eventHandler) {
let canRemoveEvent = !handler;
if (handler !== undefined) {
eventHandler.subscriptionSet.delete(handler);
canRemoveEvent = !eventHandler.subscriptionSet.size;
}
if (canRemoveEvent) {
if (this.connection) {
this.connection.off(event, eventHandler.handler);
}
this.eventHandlerMap.delete(event);
}
}
}
return this;
}
start () {
if (this.isStarted) { return; }
this.isStarted = true;
const connection = this.connection = new signalR.HubConnectionBuilder()
.withUrl(this.url)
.configureLogging(signalR.LogLevel.Debug)
.build();
for (const [event, eventHandler] of this.eventHandlerMap) {
connection.on(event, eventHandler.handler);
}
connection.onclose((error) => {
console.debug(`Connection to ${this.url} closed.`);
if (!this.closeGracefully) {
console.error(error);
this.restart();
}
this.closeGracefully = false;
});
connection.start()
.then(c => console.debug(`Connection to ${this.url} established.`))
.catch(error => {
console.debug(`Cannot connect to ${this.url}.`);
console.error(error);
setTimeout(() => this.restart(), this.autoReloadTimeout);
});
};
stop () {
this.closeGracefully = true;
this.connection.stop();
this.isStarted = false;
}
restart () {
this.isStarted = false;
this.start();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment