Created
September 3, 2013 06:12
-
-
Save clintberry/6420200 to your computer and use it in GitHub Desktop.
Websocket service with pending functions until websocket opened.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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; | |
}); |
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
The key thing to note here is in sendRequest function on line #62 - we check to see if we are connected to the websocket, if not, we store that request for later. What has NOT been implemented in this gist yet, is when the websocket connects, it needs to check to see if there are any pending requests and send them off.
Hope that helps!