I am upgrading a traditional jQuery based app by converting a few parts of it into ReactJs components and use Socket.io for the data transfer medium.
There are a few React components spread across the page. The React components will receive updates from the socket connection in their componentDidMount
method.
For example:
componentDidMount: function(){
socket.on('connect', function(data){....});
socket.on('anotherEvent', function(data){....})
}
Now, the thing is that the React components will be scattered across the page and will not be under a single app structure, and they will be subscribing to the same socket events to stay in sync.
For this, I wrote the below Socket.io wrapper, this way multiple subscriptions for the same events can be avoided but all the interested React components can be notified on an event update.
window.socketEvents = (function(){
var socket = io.connect("http://localhost:3000"),
events = {}, //events structure = {'event_name':subscribers:[callback functions], isSubscribed:true}
callOnConnect = [];
var _register = function(event, callback){
events[event] = events[event] || {};
events[event].subscribers = events[event].subscribers || [];
events[event].subscribers.push(callback);
};
var _subscribe = function(event){
console.log('Subscribingto: ', event);
socket.on(event, function(data){ // notifiy the subscribers of this event by firing their callbacks.
console.log('received evt: ', data);
for(var cb=0;cb<events[event].subscribers.length;cb++){
events[event].subscribers[cb](data);
};
});
events[event].isSubscribed = true;
};
var _emit = function(event, data, onConnect){
console.log('_emit called for: ', event);
socket.emit(event, data);
if(onConnect){
callOnConnect.push(function(){
socket.emit(event, data);
});
}
};
var _listen = function(event, callback){
_register(event, callback);
if(!events[event].isSubscribed){
_subscribe(event);
};
};
setTimeout(function(){ // register a little late to avoid multiple callbacks.
socket.on('connect', function(){
console.log('connect fired');
for(var i=0;i<callOnConnect.length;i++){
callOnConnect[i]();
}
});
},1000);
return {
listen: _listen,
emit: _emit
}
})();
React example with the new wrapper:
In ReactClassOne
:
componentDidMount: function(){
socketEvents.emit('join_service', {name:'Some name'}, true); // the third boolean param states that should the event be emitted if the socket disconnects and then reconnects.
socketEvents.listen('anotherEvent', function(data){...})
}
In ReactClassTwo
:
componentDidMount: function(){
socketEvents.emit('join_service', {name:'Some name'}, true);
socketEvents.listen('anotherEvent', function(data){...})
}
The code is currently working fine during the preliminary development but I am worried about the timeout in the socketEvents
. So, I would like this to be reviewed.