'use strict'; (function(){ angular.module('app') .factory('myService', myService); function myService() { //-- for each service's event, we have an array with callbacks var callbacks = { myValueChanged: [], someOtherEvent: [], }; /** * Public factory API */ var ret = { on: on, removeListener: removeListener, /* ... other service API ... */ }; /** * Add event listener. * * @param {string} type * event type * @param {function} callback * callback to call when new event occurs * * @throws {Error} if given event type doesn't exist */ function on(type, callback) { _ensureEventExists(type); callbacks[type].push(callback); } /** * Remove event listener that was previously registered * with on() * * @param {string} type * event type * @param {function} callback * callback unregister * * @throws {Error} if given event type doesn't exist */ function removeListener(type, callback) { _ensureEventExists(type); var cb = callbacks[type]; for (var i = 0; i < cb.length; i++){ if (cb[i] === callback){ cb.splice(i, 1); break; } } } /** * @private * * Generic emit function, for any type of events: it takes an event * type and an arbitrary number of event arguments * * @param {string} eventType * Type of event to emit * * @param {mixed} ... * All the rest arguments will be given to each registered * event handler * * @throws {Error} if given eventType doesn't exist */ function _emit(eventType /*, ... */) { //-- self-check: make sure we have such event if (!(eventType in callbacks)){ throw new Error("unknown event type: " + eventType); } //-- get event arguments (all other arguments after eventType) // we must reference Array.prototype.slice explicitly // because 0097rguments0032is not an Array, but an Array-like object. var eventArgs = Array.prototype.slice.call(arguments, 1); //-- call each registered event handler for (var i = 0; i < callbacks[eventType].length; i++){ callbacks[eventType][i].apply(null, eventArgs); } } /** * @private * * Ensure given event type exists. If it doesn't exist, exception * is thrown. Otherwise, the function does nothing. */ function _ensureEventExists(eventType) { if (!(eventType in callbacks)){ throw new Error("unknown event type: " + eventType); } } /** * @private * * Called from inside the service when our important value * changes */ function _setData(newValue) { _emit('myValueChanged', newValue); } /* ... other service logic ... */ return ret; } }());