1 | /* |
||
2 | This abstraction presents the Socket.io (and potentially other |
||
3 | transports) as an EventEmiiter. It takes care of forwarding |
||
4 | the messages between the emitter and the message transport. |
||
5 | */ |
||
6 | (function () { |
||
7 | var socketIOtoEmitterBridge = function (socket, emitter) { |
||
8 | this.socket = socket; |
||
9 | var self = this; |
||
10 | this.emitter = emitter; |
||
11 | this.senderID = generateUUID(); |
||
12 | this.cleanupFunctions = []; |
||
13 | //Every time something emits on the EventEmitter, we need to forward those on to the socket.IO. Technically we could improve |
||
14 | //on this by handling it like we do the SocketIO->eventEmitter below, by listening to the registrations in Socket.IO and only |
||
15 | //forwarding those messages when something emits them on the emitter. But then again, socket.IO is probablly already doing that |
||
16 | //filtering for us... so it might just add complexity with no real gain. |
||
17 | //Apparently socket checks the last variable for a function callback and |
||
18 | //does magic. Have to send only the right number of arguments. |
||
19 | var ignoreEvents = [ |
||
20 | 'newListener', |
||
21 | 'removeListener' |
||
22 | ]; |
||
23 | emitter.onAny(function () { |
||
24 | if (!ignoreEvents.includes(this.event)) { |
||
25 | var args = new Array(arguments.length); |
||
26 | for (var i = 0; i < args.length; ++i) { |
||
27 | //i is always valid index in the arguments object |
||
28 | args[i] = arguments[i]; |
||
29 | } |
||
30 | if (args[args.length - 1] === self.senderID) { |
||
31 | return; |
||
32 | } |
||
33 | if (args[0] == this.event) { |
||
34 | args.shift(); //to catch behavior change of onyAny after ugprade |
||
35 | } |
||
36 | //args.push(self.senderID) |
||
37 | socket.emit.apply(socket, [this.event].concat(args)); //console.log("Socket <1- ",this.event); |
||
38 | } |
||
39 | }); |
||
40 | //If the emitter has a withHistory function, we need to bridge to the data cache in the socket.io system. We do so by |
||
41 | //checking for the last value in the cache and "seeding" the cache in the emitter with the value before letting the |
||
42 | //original withHistory call take place. |
||
43 | if (emitter.withHistory) { |
||
44 | var orig_wh = emitter.withHistory.on; |
||
45 | emitter.withHistory.on = function (type, fn) { |
||
46 | self.socket.emit('fromcache', type, function () { |
||
47 | if (arguments.length == 0){ |
||
0 ignored issues
–
show
|
|||
48 | return; |
||
49 | } |
||
50 | var args = new Array(arguments.length); |
||
51 | for (var i = 0; i < args.length; ++i) { |
||
52 | args[i] = arguments[i]; |
||
53 | } |
||
54 | if (args[args.length - 1] === self.senderID) { |
||
55 | return; |
||
56 | } |
||
57 | // This is the hook to update the socket cache used in app.js to prepopulate the last messages |
||
58 | if (self.socket.lvcCache) { |
||
59 | self.socket.lvcCache[type]=args; |
||
60 | } |
||
61 | args.push(self.senderID); |
||
62 | emitter.emit.apply(emitter, [type].concat(args)); //TODO: If this works, use the args pattern for performance. |
||
63 | // console.log("Socket -2> ",type); |
||
64 | }); |
||
65 | orig_wh(type, fn); |
||
66 | }; |
||
67 | this.cleanupFunctions.push(function () { |
||
68 | emitter.withHistory.on = orig_wh; |
||
69 | }); |
||
70 | } |
||
71 | var listeningTo = {}; |
||
72 | var linkSocketIOEventToEmitter = function (aType) { |
||
73 | if (listeningTo[aType] === undefined) { |
||
74 | var handleEvent = function () { |
||
75 | var args = new Array(arguments.length); |
||
76 | for (var i = 0; i < args.length; ++i) { |
||
77 | //i is always valid index in the arguments object |
||
78 | args[i] = arguments[i]; |
||
79 | } |
||
80 | args = args.filter(function (item) { |
||
81 | return item !== null; |
||
82 | }); |
||
83 | if (args[args.length - 1] === self.senderID) { |
||
84 | return; |
||
85 | } |
||
86 | args.push(self.senderID); |
||
87 | self.emitter.emit.apply(self.emitter, [aType].concat(args)); //console.log("Socket -3> ",aType); |
||
88 | }; |
||
89 | self.socket.on(aType, handleEvent); |
||
90 | self.cleanupFunctions.push(function () { |
||
91 | self.socket.off(aType, handleEvent); |
||
92 | }); |
||
93 | listeningTo[aType] = true; |
||
94 | self.socket.emit('fromcache', aType, function () { |
||
95 | if (arguments.length == 0) { |
||
0 ignored issues
–
show
It is recommended to use
=== to compare with 0 .
Generally, it is recommended to use strict comparison whenever possible and not to rely on the weaker type-juggling comparison operator. ![]() |
|||
96 | return; |
||
97 | } |
||
98 | var args = new Array(arguments.length); |
||
99 | for (var i = 0; i < args.length; ++i) { |
||
100 | //i is always valid index in the arguments object |
||
101 | args[i] = arguments[i]; |
||
102 | } |
||
103 | args = args.filter(function (item) { |
||
104 | return item !== null; |
||
105 | }); |
||
106 | if (args[args.length - 1] === self.senderID) { |
||
107 | return; |
||
108 | } |
||
109 | args.push(self.senderID); |
||
110 | emitter.emit.apply(self.emitter, [aType].concat(args)); //TODO: If this works, use the args pattern for performance. |
||
111 | //console.log("Socket -4> ",aType); |
||
112 | }); |
||
113 | } |
||
114 | }; |
||
115 | //The emitter might already have listeners, if so we need to wire those up to Socket.IO |
||
116 | Object.keys(emitter._events).forEach(function (event) { |
||
117 | linkSocketIOEventToEmitter(event); |
||
118 | }); |
||
119 | //Everytime a function registers a listener with the eventEmitter, we need to also register that event with socket.IO so that |
||
120 | //it will send along those messages. When the messages arrive, we need to then emit them on the EventEmitter. |
||
121 | emitter.on('newListener', function (aType, aListener) { |
||
122 | if (aType !== '*') { |
||
123 | linkSocketIOEventToEmitter(aType); |
||
124 | } |
||
125 | }); |
||
126 | return this; |
||
127 | }; |
||
128 | //This will undo the linkage between the emitter and the socket. |
||
129 | socketIOtoEmitterBridge.prototype.stop = function stop() { |
||
130 | cleanupFunctions.forEach(function (fn) { |
||
131 | fn(); |
||
132 | }); |
||
133 | cleanupFunctions = []; |
||
134 | }; |
||
135 | window.SocketIOtoEmitterBridge = socketIOtoEmitterBridge; |
||
136 | }()); |
Generally, it is recommended to use strict comparison whenever possible and not to rely on the weaker type-juggling comparison operator.
Read more about comparison operations.