@obsidize/rx-map
Version:
ES6 Map with rxjs extensions for change detection
89 lines (88 loc) • 2.88 kB
JavaScript
import { Subject } from 'rxjs';
import { filter, map, share } from 'rxjs/operators';
import { MapStateChangeEventType } from '../events/map-state-change-event';
import { isActionableChangeDetectionResultType } from '../events/change-detection-event';
import { extractChanges } from '../common/utility';
import { ImmutableMap } from './immutable-map';
/**
* Extension of the standard ES6 Map with rxjs change event observables tacked on.
*/
export class RxMap {
constructor(source) {
this.source = source;
this.mStateChangeSubject = new Subject();
this.allChanges = this.mStateChangeSubject.asObservable().pipe(share());
this.changes = this.allChanges.pipe(map(ev => extractChanges(ev)), filter(ev => isActionableChangeDetectionResultType(ev.changeType)), share());
}
/**
* Generate an RxMap instance with a standard (mutable) Map store.
*/
static mutable() {
return new RxMap(new Map());
}
/**
* Generate an RxMap instance with an immutable backend store.
*/
static immutable() {
return new RxMap(ImmutableMap.standard());
}
emit(type, key, value, previousValue, context = { source: 'unknown' }) {
this.mStateChangeSubject.next({ type, key, value, previousValue, context });
}
emitSet(key, value, previousValue, context) {
this.emit(MapStateChangeEventType.SET, key, value, previousValue, context);
}
emitDelete(key, value, context) {
this.emit(MapStateChangeEventType.DELETE, key, value, undefined, context);
}
get size() {
return this.source.size;
}
get [Symbol.toStringTag]() {
return 'RxMap';
}
[Symbol.iterator]() {
return this.entries();
}
get(key) {
return this.source.get(key);
}
has(key) {
return this.source.has(key);
}
entries() {
return this.source.entries();
}
keys() {
return this.source.keys();
}
values() {
return this.source.values();
}
forEach(callbackfn) {
this.source.forEach(callbackfn);
}
destroy() {
const s = this.mStateChangeSubject;
if (s.closed && s.isStopped)
return;
s.error('destroyed');
s.unsubscribe();
}
clear() {
const keys = Array.from(this.keys());
keys.forEach(key => this.delete(key));
}
delete(key, context) {
const value = this.get(key);
const didDelete = this.source.delete(key);
this.emitDelete(key, value, context);
return didDelete;
}
set(key, value, context) {
const previousValue = this.get(key);
this.source.set(key, value);
this.emitSet(key, value, previousValue, context);
return this;
}
}