Skip to content

Instantly share code, notes, and snippets.

@tsuz
Forked from yitsushi/EventSystem.js
Last active October 18, 2018 16:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tsuz/1c584c248e63d3a9b835e3f4e2223571 to your computer and use it in GitHub Desktop.
Save tsuz/1c584c248e63d3a9b835e3f4e2223571 to your computer and use it in GitHub Desktop.
EventSystem that I use with React.js to communicate between components
"use strict"
class EventSystem{
constructor() {
this.queue = {};
this.maxNamespaceSize = 50;
}
publish(/** namespace **/ /** arguments **/) {
if(arguments.length < 1) {
throw "Invalid namespace to publish";
}
var namespace = arguments[0];
var queue = this.queue[namespace];
if (typeof queue === 'undefined' || queue.length < 1) {
console.log('did not find queue for %s', namespace);
return false;
}
var valueArgs = Array.prototype.slice.call(arguments);
valueArgs.shift(); // remove namespace value from value args
queue.forEach(function(callback) {
callback.apply(null, valueArgs);
});
return true;
}
subscribe(/** namespace **/ /** callback **/) {
const namespace = arguments[0];
if(!namespace) throw "Invalid namespace";
const callback = arguments[arguments.length - 1];
if(typeof callback !== 'function') throw "Invalid callback method";
if (typeof this.queue[namespace] === 'undefined') {
this.queue[namespace] = [];
}
const queue = this.queue[namespace];
if(queue.length === this.maxNamespaceSize) {
console.warn('Shifting first element in queue: `%s` since it reached max namespace queue count : %d', namespace, this.maxNamespaceSize);
queue.shift();
}
// Check if this callback already exists for this namespace
for(var i = 0; i < queue.length; i++) {
if(queue[i] === callback) {
throw ("The exact same callback exists on this namespace: " + namespace);
}
}
this.queue[namespace].push(callback);
return [namespace, callback];
}
unsubscribe(/** array or topic, method **/) {
let namespace;
let callback;
if(arguments.length === 1) {
let arg = arguments[0];
if(!arg || !Array.isArray(arg)) throw "Unsubscribe argument must be an array";
namespace = arg[0];
callback = arg[1];
}
else if(arguments.length === 2) {
namespace = arguments[0];
callback = arguments[1];
}
if(!namespace || typeof callback !== 'function') throw "Namespace must exist or callback must be a function";
const queue = this.queue[namespace];
if(queue) {
for(var i = 0; i < queue.length; i++) {
if(queue[i] === callback) {
queue.splice(i, 1); // only unique callbacks can be pushed to same namespace queue
return;
}
}
}
}
setNamespaceSize(size) {
if(!this.isNumber(size)) throw "Queue size must be a number";
this.maxNamespaceSize = size;
return true;
}
isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
}
const es = new EventSystem();
const namespace = 'topic';
const onData = function() {
console.log('topic: %s args %o',namespace, arguments);
};
const subscriber = es.subscribe(namespace, onData);
// to unsubscribe event
// es.unsubscribe(subscriber);
// or es.unsubscribe(namespace, onData);
es.publish(namespace, '2355', 123, {a: 'b'});
"use strict";
class ComponentOne extends React.Component {
getInitialState() {
EventSystem.publish('error.http', 'SERVER_ERROR_EXCEPTION', 'Oops.. Something went wrong..');
}
render() {
}
}
class NotificationComponent extends React.Component {
getInitialState() {
return {
// optional. see alternative below
subscriber: null
};
}
errorHandler() {
const topic = arguments[0];
const label = arguments[1];
console.log('Topic %s label %s', topic, label);
}
componentDidMount() {
var subscriber = EventSystem.subscribe('error.http', this.errorHandler);
this.state.subscriber = subscriber;
}
componentWillUnmount() {
EventSystem.unsubscribe(this.state.subscriber);
// or to not to hold extra stuff in `this.state`,
// alternative is to do:
//
// EventSystem.unsubscribe('error.http', this.errorHandler);
}
render() {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment