websocket.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /**
  2. *
  3. * MDN文档参考:https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
  4. */
  5. ;(function(root, factory){
  6. var ws = factory(root);
  7. if(typeof define === 'function' && define.amd){
  8. define([],factory);
  9. }else if(typeof module !== 'undefined' &&module.exports){
  10. module.exports=factory();
  11. }else{
  12. root.ws = factory();
  13. }
  14. }(this, function(root, undefined){
  15. if(!('WebSocket' in window)) return;
  16. var _handlers = {},wsocket,
  17. eventTarget = document.createElement('div'),
  18. settings = {
  19. //是否自动重连
  20. automaticOpen: true,
  21. //自动重连延迟重连速度速度
  22. reconnectDecay: 1.5
  23. },
  24. func = function () {},
  25. //对外泄露 API 😄
  26. _api = {
  27. CONNECTING: WebSocket.CONNECTING,
  28. OPEN: WebSocket.OPEN,
  29. CLOSING: WebSocket.CLOSING,
  30. CLOSED: WebSocket.CLOSED
  31. };
  32. /**
  33. * [ws]
  34. * @param 参数 url 为建立连接的URL
  35. * @param 参数 protocols 为服务器选择的子协定
  36. * @param 参数 options 初始化定义参数
  37. */
  38. function ws(url, protocols, options){
  39. var self = this;
  40. //websocket url
  41. this.url = url;
  42. //websocket 状态
  43. this.readyState = WebSocket.CONNECTING;
  44. /**
  45. * http://tools.ietf.org/html/rfc6455
  46. * 服务器选择的子协定,这是建立 WebSocket 对象时 protocols 参数里的其中一个字符串。
  47. */
  48. this.protocol = protocols ? protocols : null;
  49. // 绑定选项定义设置
  50. if (!options) {options = {};}
  51. for (var key in settings) {
  52. if (typeof options[key] !== 'undefined') this[key] = options[key];
  53. else this[key] = settings[key];
  54. }
  55. // 公开 API
  56. for(var a in _api) this[a] = _api[a];
  57. //用事件处理程序
  58. eventTarget.addEventListener('open', function(event) {self!==window&&self.onopen(event); });
  59. eventTarget.addEventListener('close', function(event) {self!==window&&self.onclose(event); });
  60. eventTarget.addEventListener('connecting', function(event) {self!==window&&self.onconnecting(event); });
  61. eventTarget.addEventListener('message', function(event) {self!==window&&self.onmessage(event); });
  62. eventTarget.addEventListener('error', function(event) {self!==window&&self.onerror(event); });
  63. // 公开事件目标的API
  64. this.addEventListener = eventTarget.addEventListener.bind(eventTarget);
  65. this.removeEventListener = eventTarget.removeEventListener.bind(eventTarget);
  66. this.dispatchEvent = eventTarget.dispatchEvent.bind(eventTarget);
  67. if(this.automaticOpen === true&&this!==window) this.open();
  68. return this;
  69. }
  70. /**
  71. * [generateEvent 该函数产生一个事件,与标准兼容,兼容的浏览器和IE9 - IE11?]
  72. * http://stackoverflow.com/questions/19345392/why-arent-my-parameters-getting-passed-through-to-a-dispatched-event/19345563#19345563
  73. * https://msdn.microsoft.com/library/ff975299(v=vs.85).aspx
  74. * @param eventName 位字符串类型的事件名字
  75. * @param 参数的args对象的可选对象,该事件将使用
  76. */
  77. function generateEvent(eventName, args) {
  78. var evt = document.createEvent("CustomEvent");
  79. evt.initCustomEvent(eventName, false, false, args);
  80. return evt;
  81. }
  82. ws.prototype.onconnecting = func;
  83. ws.prototype.onerror = func;
  84. ws.prototype.onopen = func;
  85. ws.prototype.onmessage = func;
  86. /**
  87. * [send 发送 websocket 消息]
  88. * @param 参数 data 为发消息的内容
  89. */
  90. ws.prototype.send = function (data) {
  91. if(this.wsocket) this.wsocket.send(data);
  92. else{
  93. throw 'INVALID_STATE_ERR : Pausing to reconnect websocket';
  94. }
  95. };
  96. /**
  97. * [close 关闭 websocket 连接。]
  98. * 如果已经关闭了连接,此方法不起作用。
  99. *
  100. * 错误代码参考:https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
  101. * @param 参数 code 为错误代码 1000为正常关闭
  102. * @param 参数 reason 为错误理由
  103. */
  104. ws.prototype.close = function (code, reason){
  105. // 默认CLOSE_NORMAL代码
  106. if (typeof code === 'undefined') code = 1000;
  107. if (this.wsocket) this.wsocket.close(code, reason);
  108. };
  109. /**
  110. * [open 打开建立 websocket 握手连接]
  111. */
  112. ws.prototype.open = function () {
  113. var self = this;
  114. wsocket = new WebSocket(this.url, this.protocol || []);
  115. eventTarget.dispatchEvent(generateEvent('connecting'));
  116. wsocket.onopen = function(event) {
  117. self.protocol = ws.protocol;
  118. self.readyState = WebSocket.OPEN;
  119. var e = generateEvent('open');
  120. eventTarget.dispatchEvent(e);
  121. };
  122. wsocket.onclose = function(event) {
  123. self.readyState = WebSocket.CLOSED;
  124. var e = generateEvent('connecting');
  125. e.code = event.code;
  126. e.reason = event.reason;
  127. e.wasClean = event.wasClean;
  128. eventTarget.dispatchEvent(e);
  129. eventTarget.dispatchEvent(generateEvent('close'));
  130. };
  131. wsocket.onmessage = function(event) {
  132. var e = generateEvent('message');
  133. e.data = event.data;
  134. eventTarget.dispatchEvent(e);
  135. };
  136. wsocket.onerror = function(event) {
  137. var e = generateEvent('error');
  138. eventTarget.dispatchEvent(e);
  139. };
  140. this.wsocket = wsocket;
  141. return this;
  142. };
  143. return ws;
  144. }));