Skip to content

Instantly share code, notes, and snippets.

@clintberry
Created September 3, 2013 06:12
Show Gist options
  • Save clintberry/6420200 to your computer and use it in GitHub Desktop.
Save clintberry/6420200 to your computer and use it in GitHub Desktop.
Websocket service with pending functions until websocket opened.
'use strict';
angular.module('guiApp')
.service('Websocket', function Websocket($q, $rootScope, PubSub) {
var Service = {}; // Object to return for the service
var callbacks = {}; // Keep all pending requests here until they get responses
var currentCallbackId = 0; // Create a unique callback ID to map requests to responses
var ws = null; // Initialize our websocket variable
var connectStatus = false; // Is the websocket connected?
var authStatus = false; // Are we authorized?
var disconnects = 0; // How many times have we disconnected and retried (used for calculating retry wait)
var retryWaitMax = 120; // Maximum amount of time to wait for a re-connect attempt
var pendingRequests = []; // Any requests coming in before we connect are stored and run when connected
Service.connect = function(address) {
console.log('Connecting to websocket...');
address = address || 'http://localhost:7777/freeswitch/';
ws = new window.SockJS(address);
ws.onopen = function() {
console.log('Socket has been opened!');
connectStatus = true;
PubSub.broadcast('socket_connect', {});
authorize();
};
ws.onmessage = function(message) {
listener(JSON.parse(message.data));
};
ws.onclose = function() {
console.log('Socket has closed');
connectStatus = false;
PubSub.broadcast('socket_close', {});
disconnects++;
var retryWait = Math.pow(2, disconnects);
if(retryWait > retryWaitMax) {
disconnects--;
retryWait = retryWaitMax;
}
console.log('Retrying in ' + retryWait + ' seconds...');
setTimeout(Service.connect, retryWait * 1000);
};
};
function authorize(user, password) {
var creds = user + password;
authStatus = true;
PubSub.broadcast('socket_authorize', creds);
return true;
}
function sendRequest(request) {
var defer = $q.defer();
var callbackId = getCallbackId();
callbacks[callbackId] = {
time: new Date(),
cb:defer
};
request.callback_id = callbackId;
if(!connectStatus) {
console.log('Saving request until connected');
pendingRequests.push(request);
}
else {
console.log('Sending request', request);
ws.send(JSON.stringify(request));
}
return defer.promise;
}
function listener(data) {
var messageObj = data;
console.log('Received data from websocket: ', messageObj);
// If an object exists with callback_id in our callbacks object, resolve it
if(callbacks.hasOwnProperty(messageObj.callback_id)) {
console.log(callbacks[messageObj.callback_id]);
$rootScope.$apply(callbacks[messageObj.callback_id].cb.resolve(messageObj.data));
delete callbacks[messageObj.callbackID];
}
else if(messageObj.hasOwnProperty('Event-Name')) {
PubSub.broadcast(messageObj['Event-Name'], messageObj);
}
}
// This creates a new callback ID for a request
function getCallbackId() {
currentCallbackId += 1;
if(currentCallbackId > 10000) {
currentCallbackId = 0;
}
return currentCallbackId;
}
/**
* Subscribe to a freeswitch event
* @param {String} eventName
* @return {Promise}
*/
Service.subscribe = function(eventName) {
var request = {
type: 'subscribe',
event_name: eventName
};
// Storing in a variable for clarity on what sendRequest returns
var promise = sendRequest(request);
return promise;
};
Service.connect();
return Service;
});
@4day
Copy link

4day commented Aug 13, 2014

line #80 must be delete callbacks[messageObj.callback_id];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment