call(back)
FrontendmediumSign in to star problems

StoreData with Change Listeners

Implement StoreData, a Backbone.Model-style key/value store with change listeners.

store.add(key, value)   // alias: set. Returns the store (chainable).
store.get(key)          // current value, or undefined
store.has(key)          // true while the key holds a value
store.remove(key)       // alias: unset. Soft-delete; true if something was removed
store.on(event, cb)     // register a listener; returns an unsubscribe function
store.once(event, cb)   // fires at most once
store.off(event, cb)    // remove one listener (all for the event when cb is omitted)
store.toJSON()          // plain object of the live keys

Events

  • "change:name" and plain "name" mean the same thing: the key name changed.
  • "change" is global — fires for every key that changes.
  • "unset" fires when a key is removed.
  • Every callback receives (oldValue, newValue, key); a removal reports newValue as undefined.

Rules

  • A set that doesn't change the value (Object.is) fires nothing.
  • Key listeners fire before global listeners.
  • One throwing listener must not stop the others.
  • Removal is a soft delete: has reports false and get returns undefined, but keep the tombstone.

Hints

Hint 1

Two Maps: attributes (key → {value, deleted}) and listeners (eventKey → Set of callbacks). Normalize every accepted event spelling to one internal key in a single place.

Hint 2

Namespace attribute events (attr:name) so a key literally called "change" can't collide with the global event — getting that normalization wrong is the classic bug here.

Hint 3

When firing, iterate over a copy of the Set and wrap each call in try/catch: a listener may unsubscribe another mid-loop, and one that throws must not silence the rest.

Asked at