-
-
Save tsuz/1c584c248e63d3a9b835e3f4e2223571 to your computer and use it in GitHub Desktop.
EventSystem that I use with React.js to communicate between components
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"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'}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"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