I'm looking for a way to trigger an event when an object is added to a Map or Set? Something like this, is it possible? Right now we're just using a timer to check.
let mymap = new Map() // or Set()
mymap.on('set', obj => {
console.log(obj)
}
This is my first pass based on @PsychoX's recommendations, thoughts?
const EventEmitter = require('events')
const emitter = new EventEmitter()
const Wrapper = () => {
this._set = new Set()
this.get = key => { return this._set.get(key) }
this.add = obj => {
this._set.add(obj)
emitter.emit('add', obj)
}
this.values = () => { return this._set.values() }
}
emitter.on('add', obj => {
console.log('added', obj)
})
let test = new Wrapper()
test.add({hello:'world'})
CodePudding user response:
You can extend the default Map
or use proxy.
My approach:
class ObservableMapChangeEvent extends Event {
constructor(observable, key, oldValue, newValue) {
super('change');
this.observable = observable;
this.key = key;
this.oldValue = oldValue;
this.newValue = newValue;
}
}
class ObservableMap extends Map {
constructor(iterable) {
super(iterable);
this._eventTarget = new EventTarget();
}
on(name, listener, options) {
this._eventTarget.addEventListener(name, listener, options);
}
off(name, listener, options) {
this._eventTarget.addEventListener(name, listener, options);
}
delete(key) {
this._eventTarget.dispatchEvent(new ObservableMapChangeEvent(this, key, this.get(key), undefined));
super.delete(key);
}
set(key, value) {
this._eventTarget.dispatchEvent(new ObservableMapChangeEvent(this, key, this.get(key), value));
super.set(key, value);
}
}
// Example:
const foo = new ObservableMap();
foo.on('change', event => {
console.log(`Changes [${event.key}] to '${event.newValue}' (old: '${event.oldValue}')`);
});
foo.set('hello', 'world'); // Changes [hello] to 'world' (old: undefined)
You might want to look at: