Advertisement
Capaj

socket.io-rpc

Apr 3rd, 2013
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /// clientside
  2.  
  3. var RPC = (function (rpc) {
  4.     var counter = 0;
  5.     var channels = {};
  6.     var deferreds = {};
  7.     var baseURL;
  8.     var rpcMaster;
  9.     var loadChannel = function (name) {
  10.         rpcMaster.emit('load channel', name);
  11.         channels[name]._loadDef = channels[name]._loadDef || Q.defer();
  12.         channels[name]._socket = io.connect(baseURL + '/rpc-' + name)
  13.             .on('return', function (data) {
  14.                 deferreds[data.toId].resolve(data.value);
  15.             })
  16.             .on('error', function (data) {
  17.                 deferreds[data.toId].reject(data.reason);
  18.             });
  19.  
  20.     };
  21.  
  22.     rpc.connect = function (url) {
  23.         baseURL = url;
  24.         rpcMaster = io.connect(url + '/rpc-master');
  25.         rpcMaster.__channelListLoad = Q.defer();
  26.         rpcMaster
  27.             .on('channels', function (data) {
  28.                 var name = data.list.pop();
  29.                 while(name) {
  30.                     channels[name] = {};
  31.                     loadChannel(name);
  32.                     name = data.list.pop();
  33.                 }
  34.                 rpcMaster.__channelListLoad.resolve(channels);
  35.             })
  36.             .on('channelFns', function (data) {
  37.                 var channelObj = channels[data.name];
  38.                 data.fnNames.forEach(function (fnName) {
  39.                     channelObj[fnName] = function () {
  40.                         counter++;
  41.                         channelObj._socket.emit('invocation',
  42.                             {Id: counter, fnName: fnName, argsArray: Array.prototype.slice.call(arguments, 0)}
  43.                         );
  44.                         deferreds[counter] = Q.defer();
  45.                         return deferreds[counter].promise;
  46.                     }
  47.                 });
  48.  
  49.                 channelObj._loadDef.resolve(channelObj);
  50.             })
  51.     };
  52.  
  53.     rpc.allChannelsLoaded = function (func) {
  54.         var promises = [];
  55.         for(var name in channels){
  56.             var channel = channels[name];
  57.             promises.push(channel._loadDef.promise)
  58.         }
  59.         Q.all(promises).then(function () {
  60.             func();
  61.         })
  62.     };
  63.     rpc.onChannelLoaded = function (name, callback) {
  64.         rpcMaster.__channelListLoad.promise.then(function (channels) {
  65.             channels[name]._loadDef = channels[name]._loadDef || Q.defer();
  66.  
  67.             channels[name]._loadDef.promise.then(function (channelObj) {
  68.                 callback(channelObj);
  69.             });
  70.         })
  71.  
  72.  
  73.     };
  74.  
  75.     return rpc;
  76. }(RPC || {}));
  77.  
  78.  
  79. /// serverside
  80. var io;
  81. var channels = {};
  82. var getChannelNames = function () {
  83.     var names = [];
  84.     for(var channel in channels){
  85.         names.push(channel);
  86.     }
  87.     return names;
  88. };
  89.  
  90. var getFnNames = function (channelName) {
  91.     var names = [];
  92.     for(var channel in channels[channelName]){
  93.         names.push(channel);
  94.     }
  95.     return names;
  96. };
  97.  
  98. module.exports = {
  99.     createMaster: function createMaster(ioP) {
  100.         io = ioP;
  101.         var rpcMaster = io
  102.             .of('/rpc-master')
  103.             .on('connection', function (socket) {
  104.                 socket.emit('channels', { list: getChannelNames() });
  105.                 socket.on('load channel', function (name) {
  106.                     if (channels.hasOwnProperty(name)) {
  107.                         socket.emit('channelFns', {name: name, fnNames: getFnNames(name)})
  108.                     }
  109.                 })
  110.             });
  111.     },
  112.     expose: function (channel, toExpose) {
  113.         ioChannel = io
  114.             .of('/rpc-'+channel)
  115.             .on('connection', function (socket) {
  116.                 socket.on('invocation', function (data) {
  117.                     if (toExpose.hasOwnProperty(data.fnName) && typeof toExpose[data.fnName] === 'function') {
  118.                         var that = toExpose['this'] || toExpose;
  119.                         var retVal = toExpose[data.fnName].apply(that, data.argsArray);
  120.                         if (typeof retVal.then === 'function') {    // this is async function, so we will emit 'return' after it finishes
  121.                             //promise must be returned in order to be treated as async
  122.                             retVal.then(function (asyncRetVal) {
  123.                                 socket.emit('return', { toId: data.Id, value: asyncRetVal });
  124.                             }, function (error) {
  125.                                 socket.emit('error', { toId: data.Id, reason: error });
  126.                             });
  127.                         } else {
  128.                             socket.emit('return', { toId: data.Id, value: retVal });
  129.                         }
  130.  
  131.                     } else {
  132.                         socket.emit('error', {toId: data.Id, reason: 'no such function has been exposed: ' + data.fnName });
  133.                     }
  134.                 });
  135.             });
  136.  
  137. //        channels[channel] = ioChannel;
  138.         channels[channel] = toExpose;
  139.  
  140.     }
  141. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement