diff --git a/test/listen-to-actions.js b/test/listen-to-actions.js new file mode 100644 index 00000000..3074eb8d --- /dev/null +++ b/test/listen-to-actions.js @@ -0,0 +1,45 @@ +import assert from 'assert' +import Alt from '../dist/alt-with-runtime' + +import ActionListeners from '../utils/ActionListeners' + +let alt = new Alt() + +class MyActions { + constructor() { + this.generateActions('updateName') + } +} + +let myActions = alt.createActions(MyActions) + +let listener = new ActionListeners(alt) + +export default { + 'listen to actions globally'() { + let id = listener.addActionListener(myActions.UPDATE_NAME, (name) => { + assert.equal(name, 'yes', 'proper data was passed in') + }) + + assert.equal(typeof id, 'string', 'the dispatcher id is returned for the listener') + + myActions.updateName('yes') + + listener.removeActionListener(id) + + myActions.updateName('no') + assert.equal(true, true, 'no error was thrown by above action since listener was removed') + + listener.addActionListener(myActions.UPDATE_NAME, (name) => { + assert.equal(name, 'mud', 'proper data was passed in again') + }) + + myActions.updateName('mud') + + listener.removeAllActionListeners() + + myActions.updateName('bill') + + assert.equal(true, true, 'all listeners were removed') + } +} diff --git a/utils/ActionListeners.js b/utils/ActionListeners.js new file mode 100644 index 00000000..6d8ce844 --- /dev/null +++ b/utils/ActionListeners.js @@ -0,0 +1,58 @@ +/** + * ActionListeners(alt: AltInstance): ActionListenersInstance + * + * > Globally listen to individual actions + * + * If you need to listen to an action but don't want the weight of a store + * then this util is what you can use. + * + * Usage: + * + * ```js + * var actionListener = new ActionListeners(alt); + * + * actionListener.addActionListener(Action.ACTION_NAME, function (data) { + * // do something with data + * }) + * ``` + */ +module.exports = ActionListeners + +var Symbol = require('es-symbol') +var ALT_LISTENERS = Symbol('global dispatcher listeners') + +function ActionListeners(alt) { + this.dispatcher = alt.dispatcher + this[ALT_LISTENERS] = {} +} + +/* + * addActionListener(symAction: symbol, handler: function): number + * Adds a listener to a specified action and returns the dispatch token. + */ +ActionListeners.prototype.addActionListener = function (symAction, handler) { + var id = this.dispatcher.register(function (payload) { + symAction === payload.action && handler(payload.data) + }) + this[ALT_LISTENERS][id] = true + return id +} + +/* + * removeActionListener(id: number): undefined + * Removes the specified dispatch registration. + */ +ActionListeners.prototype.removeActionListener = function (id) { + delete this[ALT_LISTENERS][id] + this.dispatcher.unregister(id) +} + +/** + * Remove all listeners. + */ +ActionListeners.prototype.removeAllActionListeners = function () { + Object.keys(this[ALT_LISTENERS]).forEach( + this.removeActionListener.bind(this) + ) + this[ALT_LISTENERS] = {} +}