Skip to content

Commit 149042a

Browse files
author
Gilles Ballini
authored
Merge pull request #210 from kuzzleio/refactor-event-emitters
Harmonize event emitters implementation
2 parents 332b4b1 + 8a77b58 commit 149042a

File tree

8 files changed

+429
-400
lines changed

8 files changed

+429
-400
lines changed

src/Kuzzle.js

Lines changed: 53 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
var
22
uuid = require('uuid'),
3+
KuzzleEventEmitter = require('./eventEmitter'),
34
Collection = require('./Collection.js'),
45
Security = require('./security/Security'),
56
MemoryStorage = require('./MemoryStorage'),
@@ -29,6 +30,7 @@ function Kuzzle (host, options, cb) {
2930
if (!(this instanceof Kuzzle)) {
3031
return new Kuzzle(host, options, cb);
3132
}
33+
KuzzleEventEmitter.call(this);
3234

3335
if (!cb && typeof options === 'function') {
3436
cb = options;
@@ -48,19 +50,20 @@ function Kuzzle (host, options, cb) {
4850
connectCB: {
4951
value: cb
5052
},
51-
eventListeners: {
52-
value: {
53-
connected: {lastEmitted: null, listeners: []},
54-
error: {lastEmitted: null, listeners: []},
55-
disconnected: {lastEmitted: null, listeners: []},
56-
reconnected: {lastEmitted: null, listeners: []},
57-
jwtTokenExpired: {lastEmitted: null, listeners: []},
58-
loginAttempt: {lastEmitted: null, listeners: []},
59-
offlineQueuePush: {listeners: []},
60-
offlineQueuePop: {listeners: []},
61-
queryError: {listeners: []},
62-
discarded: {listeners: []}
63-
}
53+
eventActions: {
54+
value: [
55+
'connected',
56+
'networkError',
57+
'disconnected',
58+
'reconnected',
59+
'jwtTokenExpired',
60+
'loginAttempt',
61+
'offlineQueuePush',
62+
'offlineQueuePop',
63+
'queryError',
64+
'discarded'
65+
],
66+
writeable: false
6467
},
6568
eventTimeout: {
6669
value: 200
@@ -252,39 +255,22 @@ function Kuzzle (host, options, cb) {
252255
enumerable: true
253256
});
254257

255-
/**
256-
* Emit an event to all registered listeners
257-
* An event cannot be emitted multiple times before a timeout has been reached.
258-
*/
259-
Object.defineProperty(this, 'emitEvent', {
260-
value: function emitEvent(event) {
261-
var
262-
now = Date.now(),
263-
args = Array.prototype.slice.call(arguments, 1),
264-
eventProperties = this.eventListeners[event];
265-
266-
if (eventProperties.lastEmitted && eventProperties.lastEmitted >= now - this.eventTimeout) {
267-
return false;
268-
}
269-
270-
eventProperties.listeners.forEach(function (listener) {
271-
setTimeout(function () {
272-
listener.fn.apply(undefined, args);
273-
}, 0);
274-
});
275-
276-
// Events without the 'lastEmitted' property can be emitted without minimum time between emissions
277-
if (eventProperties.lastEmitted !== undefined) {
278-
eventProperties.lastEmitted = now;
279-
}
280-
}
281-
});
282-
283258
Object.defineProperty(this, 'memoryStorage', {
284259
value: new MemoryStorage(this),
285260
enumerable: true
286261
});
287262

263+
Object.defineProperty(this, 'protectedEvents', {
264+
value: {
265+
connected: {timeout: this.eventTimeout},
266+
error: {timeout: this.eventTimeout},
267+
disconnected: {timeout: this.eventTimeout},
268+
reconnected: {timeout: this.eventTimeout},
269+
jwtTokenExpired: {timeout: this.eventTimeout},
270+
loginAttempt: {timeout: this.eventTimeout}
271+
},
272+
writeable: false
273+
});
288274

289275
if (!options || !options.connect || options.connect === 'auto') {
290276
this.connect();
@@ -309,6 +295,28 @@ function Kuzzle (host, options, cb) {
309295
});
310296
}
311297
}
298+
Kuzzle.prototype = Object.create(KuzzleEventEmitter.prototype);
299+
Kuzzle.prototype.constructor = Kuzzle;
300+
301+
/**
302+
* Emit an event to all registered listeners
303+
* An event cannot be emitted multiple times before a timeout has been reached.
304+
*/
305+
Kuzzle.prototype.emit = function(eventName) {
306+
var
307+
now = Date.now(),
308+
protectedEvent = this.protectedEvents[eventName];
309+
310+
if (protectedEvent) {
311+
if (protectedEvent.lastEmitted && protectedEvent.lastEmitted > now - protectedEvent.timeout) {
312+
return false;
313+
}
314+
protectedEvent.lastEmitted = now;
315+
}
316+
KuzzleEventEmitter.prototype.emit.apply(this, arguments);
317+
};
318+
Kuzzle.prototype.emitEvent = Kuzzle.prototype.emit;
319+
Kuzzle.prototype.off = Kuzzle.prototype.removeListener;
312320

313321
/**
314322
* Connects to a Kuzzle instance using the provided host name.
@@ -353,7 +361,7 @@ Kuzzle.prototype.connect = function () {
353361

354362
connectionError.internal = error;
355363
self.state = 'error';
356-
self.emitEvent('error', connectionError);
364+
self.emitEvent('networkError', connectionError);
357365

358366
if (self.connectCB) {
359367
self.connectCB(connectionError);
@@ -840,34 +848,19 @@ function removeAllSubscriptions() {
840848
* Adds a listener to a Kuzzle global event. When an event is fired, listeners are called in the order of their
841849
* insertion.
842850
*
843-
* The ID returned by this function is required to remove this listener at a later time.
844-
*
845-
* @param {string} event - name of the global event to subscribe to (see the 'eventListeners' object property)
851+
* @param {string} event - name of the global event to subscribe to
846852
* @param {function} listener - callback to invoke each time an event is fired
847-
* @returns {string} Unique listener ID
848853
*/
849854
Kuzzle.prototype.addListener = function(event, listener) {
850-
var
851-
knownEvents = Object.keys(this.eventListeners),
852-
listenerType = typeof listener,
853-
listenerId;
854-
855855
this.isValid();
856856

857-
if (knownEvents.indexOf(event) === -1) {
857+
if (this.eventActions.indexOf(event) === -1) {
858858
throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());
859859
}
860860

861-
if (listenerType !== 'function') {
862-
throw new Error('Invalid listener type: expected a function, got a ' + listenerType);
863-
}
864-
865-
listenerId = uuid.v4();
866-
this.eventListeners[event].listeners.push({id: listenerId, fn: listener});
867-
return listenerId;
861+
return KuzzleEventEmitter.prototype.addListener.call(this, event, listener);
868862
};
869863

870-
871864
/**
872865
* Kuzzle monitors active connections, and ongoing/completed/failed requests.
873866
* This method returns all available statistics from Kuzzle.
@@ -1367,57 +1360,6 @@ Kuzzle.prototype.query = function (queryArgs, query, options, cb) {
13671360
return self;
13681361
};
13691362

1370-
/**
1371-
* Removes all listeners, either from a specific event or from all events
1372-
*
1373-
* @param {string} event - One of the event described in the Event Handling section of this documentation
1374-
* @returns {Kuzzle} this object
1375-
*/
1376-
Kuzzle.prototype.removeAllListeners = function (event) {
1377-
var
1378-
knownEvents = Object.keys(this.eventListeners),
1379-
self = this;
1380-
1381-
if (event) {
1382-
if (knownEvents.indexOf(event) === -1) {
1383-
throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());
1384-
}
1385-
1386-
this.eventListeners[event].listeners = [];
1387-
} else {
1388-
knownEvents.forEach(function (eventName) {
1389-
self.eventListeners[eventName].listeners = [];
1390-
});
1391-
}
1392-
1393-
return this;
1394-
};
1395-
1396-
/**
1397-
* Removes a listener from an event.
1398-
*
1399-
* @param {string} event - One of the event described in the Event Handling section of this documentation
1400-
* @param {string} listenerId - The ID returned by addListener
1401-
* @returns {Kuzzle} this object
1402-
*/
1403-
Kuzzle.prototype.removeListener = function (event, listenerId) {
1404-
var
1405-
knownEvents = Object.keys(this.eventListeners),
1406-
self = this;
1407-
1408-
if (knownEvents.indexOf(event) === -1) {
1409-
throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());
1410-
}
1411-
1412-
this.eventListeners[event].listeners.forEach(function (listener, index) {
1413-
if (listener.id === listenerId) {
1414-
self.eventListeners[event].listeners.splice(index, 1);
1415-
}
1416-
});
1417-
1418-
return this;
1419-
};
1420-
14211363
/**
14221364
* Replays the requests queued during offline mode.
14231365
* Works only if the SDK is not in a disconnected state, and if the autoReplay option is set to false.

0 commit comments

Comments
 (0)