src/modules/observable.js
/**
* Minimal observable class
*/
class Observable {
/**
* Observable constructor
*/
constructor() {
/**
* Default observers class variable
*
* @type {array}
*/
this._observers = [];
}
/**
* Register callback to be called with events of specified type
*
* Callback will be called with an argument depending on the type of event.
*
* @example
* const observable = new Observable();
* const off = observable.on('foo', (data) => {
* console.log(`Foo!`, data);
* });
*
* // To stop observing events at a later time:
* off();
*
* @param {string} type - Event type
* @param {Function} callback - Event callback function
* @return {Function} - Function to be called to unregister this callback
*/
on(type, callback) {
if (typeof type !== 'string') {
throw new Error('Type argument passed to Observable#on() is not specified or not a string');
}
if (typeof callback !== 'function') {
throw new Error('Callback function passed to Observable#on() is not specified or not a function');
}
if (!this._observers[type]) {
this._observers[type] = [];
}
if (this._observers[type].indexOf(callback) === -1) {
this._observers[type].push(callback);
}
return () => {
const typeObservers = this._observers[type];
const index = typeObservers.indexOf(callback);
if (index >= 0) {
typeObservers.splice(index, 1);
}
};
}
/**
* Notify all observers of specified event type
*
* @param {string} type - Event type
* @param {*} data - Event data
*/
notify(type, data) {
if (Array.isArray(this._observers[type])) {
this._observers[type].forEach((callback) => {
try {
callback(data);
} catch (error) {
// TODO: For now log exception in console log, but consider elevating Logger property from
// Identity to Observable.
// eslint-disable-next-line no-console
console.log(error);
}
});
}
}
// TODO: Also add setValue etc. to provide an easy standard way of monitoring instance property values?
// setValue(key, value, notify = (this[key] !== value)) {
// this[key] = value;
// if (notify) {
// this.notify(key, value);
// }
// }
}
export default Observable;