Skip to content

Instantly share code, notes, and snippets.

@marlun78
Last active April 26, 2016 10:04
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 marlun78/6381a526216f353f2ee38444df02d6b5 to your computer and use it in GitHub Desktop.
Save marlun78/6381a526216f353f2ee38444df02d6b5 to your computer and use it in GitHub Desktop.
Fiddling around with some kind of observable values
/**
* An ObservableValue are like events for values. One important difference from
* events is that you are guaranteed to always get the current value when you
* subscribe. So there is no chance you subscribe “too late”. It will also
* pass you the new value together withthe old value.
* ObservableValue are similar to Angular’s `Scope.$watch`.
*
* http://jsbin.com/hokagosaru/edit?js,console
*/
// TODO: Create repo
// TODO: Write unit tests
// Create an observable value and assign it 1.
const value = new ObservableValue(1);
// The Observer object can be given to any third party that wants to
// observe the changes on this value.
const observer = value.observer;
// Call subscribe to get notified when the value changes. The handler will
// always get called immediately with the current value and undefined. The
// subscribe method returns an unsubscribe function.
const unsubscribe = observer.subscribe((newValue, oldValue) =>
console.log(['change', newValue, oldValue]));
// To change the value, call set.
value.set(2);
// To stop listening for changes, call the unsubscribe function returned from
// the subscribe call, or call unsubscribe on the observer passing in the
// original handler. Eg. `observer.unsubscribe(handler)`.
unsubscribe();
// Setting the value again after calling unsubscribe, should not trigger the
// handler.
value.set(3);
// To get the current value from the observable value, call get.
console.log(value.get());
/**
* ObservableValue rough implementation.
*/
ObservableValue.create = (defaultValue) => new ObservableValue(defaultValue);
export function ObservableValue(defaultValue) {
if (!(this instanceof ObservableValue)) {
return new ObservableValue(defaultValue);
}
let currentValue = defaultValue;
const handlers = [];
const observer = {
subscribe(handler) {
if (!isFunction(handler)) {
throw new TypeErro(handlerMustBeAFunction(handler));
}
handlers.push(handler);
handler(currentValue);
return () => this.unsubscribe(handler);
},
unsubscribe(handler) {
if (!isFunction(handler)) {
throw new TypeErro(handlerMustBeAFunction(handler));
}
const index = handlers.indexOf(handler);
if (index !== -1) {
handlers.splice(index, 1);
}
}
};
Object.defineProperty(this, 'observer', {
get() { return observer; },
set() { throw new Error('The observer is readonly'); }
});
this.get = () => currentValue;
this.set = (newValue) => {
handlers.forEach((handler) => handler(newValue, currentValue));
currentValue = newValue;
};
function isFunction(value) {
return typeof value === 'function';
}
function handlerMustBeAFunction(handler) {
return `Handler must be a function, got ${typeof handler}`;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment