UNPKG

alt

Version:
113 lines (92 loc) 2.88 kB
import * as fn from '../functions' import transmitter from 'transmitter' class AltStore { constructor(alt, model, state, StoreModel) { const lifecycleEvents = model.lifecycleEvents this.transmitter = transmitter() this.lifecycle = (event, x) => { if (lifecycleEvents[event]) lifecycleEvents[event].publish(x) } this.state = state this.alt = alt this.preventDefault = false this.displayName = model.displayName this.boundListeners = model.boundListeners this.StoreModel = StoreModel this.reduce = model.reduce || (x => x) this.subscriptions = [] const output = model.output || (x => x) this.emitChange = () => this.transmitter.publish(output(this.state)) const handleDispatch = (f, payload) => { try { return f() } catch (e) { if (model.handlesOwnErrors) { this.lifecycle('error', { error: e, payload, state: this.state, }) return false } throw e } } fn.assign(this, model.publicMethods) // Register dispatcher this.dispatchToken = alt.dispatcher.register((payload) => { this.preventDefault = false this.lifecycle('beforeEach', { payload, state: this.state, }) const actionHandlers = model.actionListeners[payload.action] if (actionHandlers || model.otherwise) { let result if (actionHandlers) { result = handleDispatch(() => { return actionHandlers.filter(Boolean).every((handler) => { return handler.call(model, payload.data, payload.action) !== false }) }, payload) } else { result = handleDispatch(() => { return model.otherwise(payload.data, payload.action) }, payload) } if (result !== false && !this.preventDefault) this.emitChange() } if (model.reduce) { handleDispatch(() => { const value = model.reduce(this.state, payload) if (value !== undefined) this.state = value }, payload) if (!this.preventDefault) this.emitChange() } this.lifecycle('afterEach', { payload, state: this.state, }) }) this.lifecycle('init') } listen(cb) { if (!fn.isFunction(cb)) throw new TypeError('listen expects a function') const { dispose } = this.transmitter.subscribe(cb) this.subscriptions.push({ cb, dispose }) return () => { this.lifecycle('unlisten') dispose() } } unlisten(cb) { this.lifecycle('unlisten') this.subscriptions .filter(subscription => subscription.cb === cb) .forEach(subscription => subscription.dispose()) } getState() { return this.StoreModel.config.getState.call(this, this.state) } } export default AltStore