rpcClient.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. export default function rpcClient(url,auto_reconnect) {
  2. var param = {"reconnection":false,"force new connection":true};
  3. this.url = url;
  4. this.socket = io.connect(this.url, param);
  5. this.connect_count = 0;
  6. this.connect_cb = '';
  7. this.reconnect_cb = '';
  8. this.cid = 0;
  9. this.response_cb_map = {};
  10. this.static_cb_map = {};//保存所有的监听回调函数
  11. this.emit_cb_map={};//保存所有的未成功连接前的回调函数
  12. this.err_cb_map = {};
  13. this.BeatTimerId = -1;
  14. this.connect_status = "undefine";
  15. this.self_close = false;
  16. this.auto_reconnect = auto_reconnect || true;
  17. var that = this;
  18. var rpc_cli = this;
  19. this.copyAllListeners = function() {
  20. for (var key in that.static_cb_map) {
  21. var fn_list = that.static_cb_map[key];
  22. fn_list.forEach(function(fun){
  23. that.socket.on(key, fun);
  24. })
  25. }
  26. };
  27. this.reconnect = function() {
  28. if ("connected" == that.connect_status || "connecting" == that.connect_status) return;
  29. that.connect_status = "connecting";
  30. that.socket = io.connect(that.url, param);
  31. that.copyAllListeners();
  32. that.self_close = false;
  33. };
  34. this.clear_err_cb = function(reconnect_time) {
  35. that.response_cb_map = {} // rm all success cb
  36. for (var key in that.err_cb_map) {
  37. var err_cb = that.err_cb_map[key];
  38. err_cb(); // exe err cb
  39. }
  40. that.err_cb_map = {};
  41. };
  42. this.close = function() {
  43. that.self_close = true;
  44. that.socket.disconnect();
  45. that.clear_err_cb();
  46. that.socket.removeAllListeners();
  47. that.connect_status = "closed";
  48. };
  49. this.close_handler = function(reconnect_time) {
  50. that.socket.disconnect();
  51. that.clear_err_cb();
  52. that.socket.removeAllListeners();
  53. that.connect_status = "closed";
  54. if (that.self_close || !auto_reconnect) return;
  55. reconnect_time = reconnect_time || 1000;
  56. setTimeout(function(){that.reconnect();},reconnect_time);
  57. };
  58. this.nextId = function() {
  59. var new_id = ++rpc_cli.cid;
  60. if (rpc_cli.cid > 999999999) {
  61. rpc_cli.cid = 0;
  62. }
  63. return new_id;
  64. };
  65. this.setBeatTime = function(beat_time, timeout) {
  66. if (that.BeatTimerId > 0) {
  67. clearInterval(that.BeatTimerId);
  68. that.BeatTimerId = -1;
  69. }
  70. if (beat_time <= 0) return;
  71. var timeout = timeout || 20000;
  72. that.BeatTimerId = setInterval(function(){
  73. if ("connected" == that.connect_status) {
  74. //console.log("rpc client send beat");
  75. that.emit('rpc_beat',"",{
  76. "success": function(){
  77. //console.log("rpc client beat suc");
  78. },
  79. "timeout_time": timeout,
  80. "timeout_cb": function(){
  81. console.log("client beat time out");
  82. that.socket.disconnect();
  83. },
  84. "error":function(){
  85. console.log("client beat error");
  86. }
  87. });
  88. }
  89. }, beat_time);
  90. };
  91. this.inner_on = function(route, cb) {
  92. var fn_list = that.static_cb_map[route] || new Array();
  93. fn_list.push(cb);
  94. that.static_cb_map[route] = fn_list;
  95. that.socket.on(route, function(data){
  96. cb(data);
  97. });
  98. }
  99. this.on = function(route, cb) {
  100. if ("connect" == route) {
  101. if (that.connect_status == "connected") cb();
  102. else that.connect_cb = cb;
  103. return;
  104. }
  105. if ("reconnect" == route) {
  106. that.reconnect_cb = cb;
  107. return;
  108. }
  109. that.inner_on(route, cb);
  110. };
  111. // rpc response
  112. this.on("rpc_response", function (data){
  113. if ("rpc_cid" in data && data.rpc_cid in that.response_cb_map) {
  114. var suc_cb = that.response_cb_map[data.rpc_cid];
  115. var suc_data = data.rpc_data || {};
  116. suc_cb(suc_data);
  117. }
  118. });
  119. // rpc request
  120. this.on("rpc_request", function (data){
  121. if (!("rpc_route" in data)) {
  122. return;
  123. }
  124. var rpc_route = data.rpc_route;
  125. if (!(rpc_route in that.static_cb_map)) {
  126. rpc_route = '*';
  127. }
  128. if (rpc_route in that.static_cb_map) {
  129. var fn_list = that.static_cb_map[rpc_route];
  130. for (var cb_key in fn_list) {
  131. var route_cb = fn_list[cb_key];
  132. var rpc_data = data.rpc_data || {};
  133. route_cb(rpc_data,function(response) {
  134. var response_json = {};
  135. response_json["rpc_cid"] = data.rpc_cid;
  136. response_json["rpc_data"] = response;
  137. that.socket.emit('rpc_response', response_json);
  138. });
  139. }
  140. }
  141. });
  142. // for beat
  143. this.on('rpc_beat', function (data, cb) {
  144. if (cb) cb("");
  145. });
  146. this.inner_on('connect',function(data){
  147. that.connect_status = "connected";
  148. that.connect_count += 1
  149. if (that.connect_count > 1) {
  150. if (typeof(that.reconnect_cb) == "function") that.reconnect_cb(data);
  151. } else {
  152. if (typeof(that.connect_cb) == "function") that.connect_cb(data);
  153. }
  154. });
  155. this.inner_on('reconnect',function(){
  156. that.connect_status = "connected";
  157. });
  158. this.on('disconnect', function(){that.close_handler(10);});
  159. this.on('connect_error', function(){that.close_handler(1000);});
  160. this.on('connect_timeout', function(){that.close_handler(1000);});
  161. //options:
  162. // success: callback for success response
  163. // error: callback for error
  164. // if has success callback:
  165. // timeout_time: time for timeout ms
  166. // timeout_cb: callback for timeout
  167. this.emit = function(route, msg, options) {
  168. options = options || {};
  169. //if (!options.success && !options.error) {// no callback
  170. if (false) {
  171. if (msg) {
  172. that.socket.emit(route,msg);
  173. } else {
  174. that.socket.emit(route);
  175. }
  176. } else {
  177. var new_id =String(that.nextId());
  178. var timeout_id;
  179. if (options.success) {
  180. // timeout callback
  181. if (options.timeout_cb) {
  182. var timeout = options.timeout_time || 10000;
  183. timeout_id = setTimeout(function() {
  184. if (new_id in that.err_cb_map) {delete that.err_cb_map[new_id];} // rm err cb
  185. if (new_id in that.response_cb_map) {
  186. delete that.response_cb_map[new_id]; // rm success cb
  187. options.timeout_cb(); // exe timeout cb
  188. }
  189. }, timeout);
  190. }
  191. // success callback
  192. var suc_cb_cb = function(suc_data) {
  193. if (new_id in that.response_cb_map) {delete that.response_cb_map[new_id];}
  194. if (new_id in that.err_cb_map) {delete that.err_cb_map[new_id];} // rm err cb
  195. if (timeout_id) {clearTimeout(timeout_id);} // rm timeout cb
  196. options.success(suc_data); // exe success cb
  197. };
  198. that.response_cb_map[new_id] = suc_cb_cb;
  199. }
  200. // err callback
  201. if (options.error) {
  202. var e_cb_cb = function() {
  203. if (new_id in that.response_cb_map) {delete that.response_cb_map[new_id];} // rm success cb
  204. if (timeout_id) {clearTimeout(timeout_id);} // rm timeout cb
  205. options.error(); // exe error cb
  206. }
  207. that.err_cb_map[new_id] = e_cb_cb;
  208. }
  209. if ("connected" != that.connect_status) {
  210. that.clear_err_cb();
  211. return;
  212. }
  213. var new_msg = {};
  214. new_msg["rpc_cid"] = new_id;
  215. new_msg["rpc_route"] = route;
  216. if (msg) {
  217. new_msg["rpc_data"] = msg;
  218. that.socket.emit("rpc_request",new_msg);
  219. } else {
  220. that.socket.emit("rpc_request",new_msg);
  221. }
  222. }
  223. };
  224. }
  225. // $.ping = function(option)
  226. // {
  227. // var ping, requestTime, responseTime ;
  228. // var getUrl = function(url){ //保证url带http://
  229. // var strReg="^((https|http)?://){1}"
  230. // var re=new RegExp(strReg);
  231. // return re.test(url)?url:"http://"+url;
  232. // }
  233. // $.ajax({
  234. // url: getUrl(option.url)+'/'+ (new Date()).getTime() + '.html', //设置一个空的ajax请求
  235. // type: 'GET',
  236. // dataType: 'html',
  237. // timeout: option.timeout || 10000,
  238. // beforeSend : function()
  239. // {
  240. // if(option.beforePing) option.beforePing();
  241. // requestTime = new Date().getTime();
  242. // },
  243. // complete : function(XMLHttpRequest,status)
  244. // {
  245. // if(status=='success'){
  246. // responseTime = new Date().getTime();
  247. // ping = Math.abs(requestTime - responseTime);
  248. // if(option.afterPing) option.afterPing(ping);
  249. // } else {
  250. // if(option.error) option.error();
  251. // }
  252. // }
  253. // });
  254. // if(option.interval && option.interval > 0)
  255. // {
  256. // var interval = option.interval;
  257. // //setTimeout(function(){$.ping(option)}, interval);
  258. // // option.interval = 0; // 阻止多重循环
  259. // // setInterval(function(){$.ping(option)}, interval);
  260. // }
  261. // };