film-exif/src/WSCache.js

153 lines
3.0 KiB
JavaScript

import bindAll from 'lodash-es/bindAll';
import { JSONMessage } from '//helpers/web-socket';
class WSCache {
constructor (ws) {
this.ws = ws;
// Websocket channels
// These hold previous messages if they are needed later
this.slots = {
'default': [],
};
// Send messages
this.sent = {
'default': [],
};
// Subscribers
this.listeners = {
'default': [console.info],
'server-log': [console.dir],
};
bindAll(this, [
'onWebSocketClose',
'onWebSocketMessage',
'publish',
'send',
'sendJSON',
'subscribe',
]);
this.ws.addEventListener('message', this.onWebSocketMessage);
this.ws.addEventListener('close', this.onWebSocketClose);
this.ws.addEventListener('error', console.error);
}
onWebSocketClose () {
this.ws = null;
console.info('WebSocket closed');
}
/**
* Callback for receiving a websocket message
*
* @param {mixed} message
*/
onWebSocketMessage (message) {
// `this` is overwritten to be the web socket object,
// so use the current instance object instead
try {
(() => {})();
const messageObject = JSON.parse(message.data);
WSCache.instance.publish(messageObject[0], messageObject[1]);
} catch (e) {
console.error('Error resolving web socket message', e);
// console.error(message);
WSCache.instance.publish('default', message.data);
}
}
/*
* Send a received websocket message to the appropriate listener(s)
*
* @param {string} slot
* @param {mixed} data
* @return {void}
*/
publish (slot, data) {
if (!this.listeners[slot] || data === undefined) {
return;
}
if (this.slots[slot] === undefined) {
this.slots[slot] = [];
}
this.slots[slot].push(data);
this.listeners[slot].forEach(listener => {
listener(data);
});
}
/**
* Send a message to the websocket server
*
* @param {mixed} message
*/
send (message) {
this.sent['default'].push(message);
return this.ws.send(message);
}
/**
* Send a JSON-encoded message to the websocket server
*
* @param {string} slot
* @param {mixed} data
*/
sendJSON (slot, data = {}) {
const sentSlots = Object.keys(this.sent);
if (!sentSlots.includes(slot)) {
this.sent[slot] = [];
}
this.sent[slot].push(data);
return this.ws.send(JSONMessage(slot, data));
}
/**
* Subscribe to a websocket message type
*
* Returns an object with a `unsubscribe` method
*
* @param {string} slot
* @param {function} cb
*/
subscribe (slot, cb) {
const slots = Object.keys(this.slots);
// Create the slots and listener arrays
if (!slots.includes(slot)) {
this.slots[slot] = [];
this.listeners[slot] = [];
}
this.listeners[slot].push(cb);
const listenerIndex = this.listeners[slot].length - 1;
return {
remove: () => {
delete this.listeners[slot][listenerIndex];
},
};
}
}
WSCache.instance = null;
export function createWsCache () {
if (WSCache.instance === null) {
const ws = new WebSocket('ws://localhost:65432/');
const instance = new WSCache(ws);
WSCache.instance = instance;
return instance;
}
return WSCache.instance;
}