UNPKG

5.36 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _Dispatcher = require('./Dispatcher');
8
9var _Dispatcher2 = _interopRequireDefault(_Dispatcher);
10
11var _GenericError = require('../error/GenericError');
12
13var _GenericError2 = _interopRequireDefault(_GenericError);
14
15function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
17/**
18 * An empty immutable map of event listener to scopes, used for a mismatch in
19 * the {@codelink _eventListeners} map.
20 *
21 * @const
22 * @type {Map<function (*), Set<?Object>>}
23 */
24const EMPTY_MAP = Object.freeze(new Map());
25
26/**
27 * An empty immutable set of event listener scopes, used for a mismatch in the
28 * {@codelink _eventListeners} map.
29 *
30 * @const
31 * @type {Set<?Object>}
32 */
33const EMPTY_SET = Object.freeze(new Set());
34
35/**
36 * Default implementation of the {@codelink Dispatcher} interface.
37 */
38class DispatcherImpl extends _Dispatcher2.default {
39 static get $dependencies() {
40 return [];
41 }
42
43 /**
44 * Initializes the dispatcher.
45 */
46 constructor() {
47 super();
48
49 /**
50 * Map of event names to a map of event listeners to a set of scopes to
51 * which the event listener should be bound when being executed due to
52 * the event.
53 *
54 * @type {Map<string, Map<function(*), Set<?Object>>>}
55 */
56 this._eventListeners = new Map();
57 }
58
59 /**
60 * @inheritdoc
61 */
62 clear() {
63 this._eventListeners.clear();
64
65 return this;
66 }
67
68 /**
69 * @inheritdoc
70 */
71 listen(event, listener, scope = null) {
72 if ($Debug) {
73 if (!(listener instanceof Function)) {
74 throw new _GenericError2.default(`The listener must be a function, ${listener} provided.`);
75 }
76 }
77
78 if (!this._eventListeners.has(event)) {
79 this._createNewEvent(event);
80 }
81 let listeners = this._getListenersOf(event);
82
83 if (!listeners.has(listener)) {
84 this._createNewListener(event, listener);
85 }
86 this._getScopesOf(event, listener).add(scope);
87
88 return this;
89 }
90
91 /**
92 * @inheritdoc
93 */
94 unlisten(event, listener, scope = null) {
95 let scopes = this._getScopesOf(event, listener);
96
97 if ($Debug) {
98 if (!scopes.has(scope)) {
99 console.warn('ima.event.DispatcherImpl.unlisten(): the provided ' + `listener '${listener}' is not registered for the ` + `specified event '${event}' and scope '${scope}'. Check ` + `your workflow.`, {
100 event: event,
101 listener: listener,
102 scope: scope
103 });
104 }
105 }
106
107 scopes.delete(scope);
108 if (!scopes.size) {
109 let listeners = this._getListenersOf(event);
110 listeners.delete(listener);
111
112 if (!listeners.size) {
113 this._eventListeners.delete(event);
114 }
115 }
116
117 return this;
118 }
119
120 /**
121 * @inheritdoc
122 */
123 fire(event, data, imaInternalEvent = false) {
124 let listeners = this._getListenersOf(event);
125
126 if (!listeners.size && !imaInternalEvent) {
127 console.warn(`There are no event listeners registered for the ${event} ` + `event`, {
128 event: event,
129 data: data
130 });
131 }
132
133 for (let [listener, scopes] of listeners) {
134 for (let scope of scopes) {
135 listener.bind(scope)(data);
136 }
137 }
138
139 return this;
140 }
141
142 /**
143 * Create new Map storage of listeners for the specified event.
144 *
145 * @param {string} event The name of the event.
146 */
147 _createNewEvent(event) {
148 let listeners = new Map();
149 this._eventListeners.set(event, listeners);
150 }
151
152 /**
153 * Create new Set storage of scopes for the specified event and listener.
154 *
155 * @param {string} event The name of the event.
156 * @param {function(*)} listener The event listener.
157 */
158 _createNewListener(event, listener) {
159 let scopes = new Set();
160 this._eventListeners.get(event).set(listener, scopes);
161 }
162
163 /**
164 * Retrieves the scopes in which the specified event listener should be
165 * executed for the specified event.
166 *
167 * @param {string} event The name of the event.
168 * @param {function(*)} listener The event listener.
169 * @return {Set<?Object>} The scopes in which the specified listeners
170 * should be executed in case of the specified event. The returned
171 * set is an unmodifiable empty set if no listeners are registered
172 * for the event.
173 */
174 _getScopesOf(event, listener) {
175 let listenersToScopes = this._getListenersOf(event);
176
177 if (listenersToScopes.has(listener)) {
178 return listenersToScopes.get(listener);
179 }
180
181 return EMPTY_SET;
182 }
183
184 /**
185 * Retrieves the map of event listeners to scopes they are bound to.
186 *
187 * @param {string} event The name of the event.
188 * @return {Map<function(*), Set<?Object>>} A map of event listeners to the
189 * scopes in which they should be executed. The returned map is an
190 * unmodifiable empty map if no listeners are registered for the
191 * event.
192 */
193 _getListenersOf(event) {
194 if (this._eventListeners.has(event)) {
195 return this._eventListeners.get(event);
196 }
197
198 return EMPTY_MAP;
199 }
200}
201exports.default = DispatcherImpl;
202
203typeof $IMA !== 'undefined' && $IMA !== null && $IMA.Loader && $IMA.Loader.register('ima/event/DispatcherImpl', [], function (_export, _context) {
204 'use strict';
205 return {
206 setters: [],
207 execute: function () {
208 _export('default', exports.default);
209 }
210 };
211});