undux
Version:
Dead simple state management for React
89 lines • 2.69 kB
JavaScript
import { Observable } from 'rxjs-observable';
const ALL = '__ALL__';
const CYCLE_ERROR_MESSAGE = '[undux] Error: Cyclical dependency detected. ' +
'This may cause a stack overflow unless you fix it. \n' +
'The culprit is the following sequence of .set calls, ' +
'called from one or more of your Undux Effects: ';
export class Emitter {
constructor(isDevMode = false) {
this.isDevMode = isDevMode;
this.state = {
callChain: new Set(),
observables: new Map(),
observers: new Map(),
};
}
/**
* Emit an event (silently fails if no listeners are hooked up yet)
*/
emit(key, value) {
if (this.isDevMode) {
if (this.state.callChain.has(key)) {
console.error(CYCLE_ERROR_MESSAGE +
Array.from(this.state.callChain).concat(key).join(' -> '));
return this;
}
else {
this.state.callChain.add(key);
}
}
if (this.hasChannel(key)) {
this.emitOnChannel(key, value);
}
if (this.hasChannel(ALL)) {
this.emitOnChannel(ALL, value);
}
if (this.isDevMode)
this.state.callChain.clear();
return this;
}
/**
* Subscribe to an event
*/
on(key) {
return this.createChannel(key);
}
/**
* Subscribe to all events
*/
all() {
return this.createChannel(ALL);
}
/// private
createChannel(key) {
if (!this.state.observers.has(key)) {
this.state.observers.set(key, []);
}
if (!this.state.observables.has(key)) {
this.state.observables.set(key, []);
}
const observable = new Observable((_) => {
this.state.observers.get(key).push(_);
return () => this.deleteChannel(key, observable);
});
this.state.observables.get(key).push(observable);
return observable;
}
deleteChannel(key, observable) {
if (!this.state.observables.has(key)) {
return;
}
const array = this.state.observables.get(key);
const index = array.indexOf(observable);
if (index < 0) {
return;
}
array.splice(index, 1);
if (!array.length) {
this.state.observables.delete(key);
this.state.observers.delete(key);
}
}
emitOnChannel(key, value) {
this.state.observers.get(key).forEach((_) => _.next(value));
}
hasChannel(key) {
return this.state.observables.has(key);
}
}
//# sourceMappingURL=emitter.js.map