Skip to content

Instantly share code, notes, and snippets.

@Zerstoren
Created November 26, 2013 11:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zerstoren/7656988 to your computer and use it in GitHub Desktop.
Save Zerstoren/7656988 to your computer and use it in GitHub Desktop.
Wrapper on WebSocket
(function() {
var Socket = function(host, port) {
this.init(host, port);
};
Socket.Counter = 0;
Socket.prototype.$super = 'Socket';
Socket.prototype.pool = null;
/**
* Автоматически иницилизатор соединения и всего остального
* @return {void}
*/
Socket.prototype.init = function(host, port) {
this.pool = [];
this.host = host;
this.port = port;
this.need_reconnect = true;
if(window.MozWebSocket && window.WebSocket === undefined) {
window.WebSocket = window.MozWebSocket;
}
this.listeners = {};
this.super('Observer', 'init', undefined);
this.registerEvents([
'close', 'connect', 'reconnect', 'connect_failed', 'error'
]);
// Bugfix for old Firefox MozWebSocket
// Don`t disconnect, before close browser
// Close socket on tab close
window.addEventListener('beforeunload', this.close.bind());
};
/**
* Установка соединения с сервером
* @param reconnect {boolean} Установить соединение, как повторное.
* @return {void}
*/
Socket.prototype.connect = function(reconnect) {
if(reconnect !== undefined) {
this.need_reconnect = reconnect;
}
if(this.ws !== undefined) {
return;
}
this.ws = new window.WebSocket('ws://' + this.host + ':' + this.port + '/');
this.ws.onopen = this.onOpen.bind(this);
this.ws.onclose = this.onClose.bind(this);
this.ws.onmessage = this.onMessage.bind(this);
this.ws.onerror = this.onError.bind(this);
};
/**
* Отправка сообщения на сервер
* @param {string} module Имя модуля
* @param {object} message Объект сообщения
* @param {function} asyncFn Callback функция, для асинхронных запросов
* @return {void}
*/
Socket.prototype.send = function(module, message, asyncFn) {
if(this.ws === undefined || this.ws.readyState !== 1) {
this.pool.push([module, message, asyncFn]);
return;
}
if(module.length !== 1 && (module[0] !== '/' || module[module.length -1] === '/')) {
throw new Error('Wrong path type');
}
var data, asyncName = false;
if(this.ws === undefined || this.ws.send === undefined) {
throw new Error('WebSocket not connected to server yet');
}
window.console.log('Send message:', module, message);
if(asyncFn) {
asyncName = Math.random();
this.listeners[asyncName] = asyncFn;
Socket.Counter += 1;
}
data = {
module: module,
message: message,
async: asyncName
};
this.ws.send(JSON.stringify(data));
};
/**
* Закрывает сокет соединение
* @return {void}
*/
Socket.prototype.close = function() {
this.need_reconnect = false;
this.ws.close();
this.ws = undefined;
this.fireEvent('close');
};
/**
* Подписка на сообщение с сервера
* @param {string} eventName Имя события, на которое происходит подписка
* @param {function} eventFn Callback функция, подписки
* @return {void}
*/
Socket.prototype.subscribe = function(eventName, eventFn) {
if(this.hasEvent(eventName) === false) {
this.registerEvents([eventName]);
}
this.super('Observer', 'subscribe', [eventName, eventFn]);
};
/**
* Отписка от сообщениф с сервера
* @param {string} eventName Имя события, от которых происходит отписка
* @param {function} eventFn Callback функция, подписки
* @return {void}
*/
Socket.prototype.unsubscribe = function(eventName, eventFn) {
this.super('Observer', 'unsubscribe', [eventName, eventFn]);
if(this.sumEventListenters(eventName) === 0) {
this.removeEvents([eventName]);
}
};
/**
* Получение сообщения с сервера
* @param {object} data Сообщение с сервера
* @return {void}
*/
Socket.prototype.onMessage = function(data) {
message = JSON.parse(data.data);
console.log('Get message:', message.module, message.message);
if(message.async !== null && this.listeners[message.async]) {
this.listeners[message.async](message.message);
delete this.listeners[message.async];
Socket.Counter -= 1;
return;
}
if(this.hasEvent(message.module)) {
this.fireEvent(message.module, message.message);
}
};
/**
* Событие открытия соединения с сервером
* @return {void}
*/
Socket.prototype.onOpen = function() {
var poolMessage;
while((poolMessage = this.pool.shift())) {
this.send.apply(this, poolMessage);
}
if(this.need_reconnect) {
this.fireEvent('reconnect');
} else {
this.fireEvent('connect');
}
};
/**
* Событие закрытия соединения с сервером
* @return {void}
*/
Socket.prototype.onClose = function() {
if(this.need_reconnect) {
var self = this;
this.ws.close();
this.ws = undefined;
setTimeout(function() {
self.connect(true);
}, 1000);
} else {
window.removeEventListener('beforeunload', this.close.bind());
this.fireEvent('close');
}
};
Socket.prototype.onError = function(a,b,c) {
this.fireEvent('error');
};
Object.extend(
Socket,
pack('COM.Extend'),
pack('COM.Events.Observer')
);
pack('COM.Socket', Socket);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment