Skip to content

Instantly share code, notes, and snippets.

@jason-s13r
Last active March 23, 2016 22:17
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 jason-s13r/7e547987c77cef5aa9fa to your computer and use it in GitHub Desktop.
Save jason-s13r/7e547987c77cef5aa9fa to your computer and use it in GitHub Desktop.
angular websockets json-rpc2 service that uses [angular-websockets](https://github.com/AngularClass/angular-websocket). JSFiddle example: https://jsfiddle.net/master5o1/bxvauLcw/
angular.module('ngWebsocketRpc', ['ngWebSocket', 'guid'])
.factory('$rpc', ['$websocket', '$q', 'guid', function($websocket, $q, guid) {
var seconds = 1000;
var history = {};
var methods = {};
var $ws;
var handlers = {
onOpen: angular.noop,
onClose: angular.noop,
onError: angular.noop
};
var rpcErrors = {
ParseError: RpcError(-32700, 'Parse error'),
InvalidRequest: RpcError(-32600, 'Invalid Request'),
MethodNotFound: RpcError(-32601, 'Method not found'),
InvalidParams: RpcError(-32602, 'Invalid params'),
InternalError: RpcError(-32603, 'Internal error'),
ServerError: RpcError(-32000, 'Server Error'),
};
function open(url) {
$ws = $websocket(url);
$ws.onMessage(messageRouter);
}
function close(force) {
return $ws.close(force);
}
function messageRouter(event, message) {
message = JSON.parse(event.data);
if (!!message.method) {
handlerMethodCall(event, message);
return;
}
handleCallResponse(event, message);
}
function handleCallResponse(event, message){
var call = history[message.id];
if (!!message.result) {
call.deferred.resolve(message.result, message, event);
return;
}
call.deferred.reject(message.error, message, event);
}
function handlerMethodCall(event, message) {
var response = {
"jsonrpc": "2.0",
"id": message.id
};
var params = message.params;
var fn = methods[message.method];
if (typeof fn === 'function'){
response = angular.extend(response, fn(params));
} else {
response = angular.extend(response, {
error: rpcErrors.MethodNotFound
});
}
var promise = $ws.send(JSON.stringify(response));
}
function callMethod(method, parameters) {
var id = guid();
var data = {
"jsonrpc": "2.0",
"method": method,
"params": parameters,
"id": id
};
var deferred = $q.defer();
var send = $ws.send(JSON.stringify(data));
history[id] = {
call: data,
messages: [],
send: send,
deferred: deferred
};
// cancel if somehow it doesn't make it to the websocket.
send.then(angular.noop, deferred.reject);
return deferred.promise;
}
function exposeMethod(method, handler){
methods[method] = handler;
}
function RpcError(code, message) {
return {
error: {
code: code,
message: message
}
};
}
function RpcResult(result) {
return {
result: result
};
}
function onEventHandlerFactory(eventName) {
return function(fn){
$ws[eventName](fn);
};
}
return {
$ws: $ws,
open: open,
close: close,
onOpen: onEventHandlerFactory('onOpen'),
onClose: onEventHandlerFactory('onClose'),
onError: onEventHandlerFactory('onError'),
call: callMethod,
expose: exposeMethod,
_: {
Result: RpcResult,
Errors: rpcErrors
}
};
}]);
angular.module('guid', [])
.factory('guid', [function() {
return function Guid() {
function S4() {
var num = (((1 + Math.random()) * 0x10000) | 0);
if (!!crypto && !!crypto.getRandomValues) {
num = crypto.getRandomValues(new Uint32Array(1))[0];
}
return num.toString(16).substring(1, 5);
}
// x = 4 characters, y = 3 characters
return 'xx-x-4y-x-xxx'.replace(/[xy]/g, function(v) {
return v === 'x' ? S4() : S4().substring(0, 3);
}).toLowerCase();
};
}]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment