market-socket.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. class Ws {
  2. constructor(ws, data, ...args) { // [{url, data, method...},,,,]
  3. this._ws = ws;
  4. this._data = data;
  5. // 待发送的消息列
  6. this._msgs = []
  7. this.socket = this.doLink();
  8. this.doOpen();
  9. // 订阅/发布模型
  10. this._events = {};
  11. // 是否保持连接
  12. this._isLink = true;
  13. // 订阅列表(交易所专用)
  14. this.subs = []
  15. // 循环检查
  16. setInterval(() => {
  17. if (this._isLink) {
  18. if (this.socket.readyState == 2 || this.socket.readyState == 3) {
  19. this.resetLink()
  20. }
  21. }
  22. }, 3000)
  23. }
  24. // 重连
  25. resetLink() {
  26. this.socket = this.doLink(() => {
  27. this.Notify({
  28. Event: 'resetLink'
  29. });
  30. this.resetSub()
  31. });
  32. this.doOpen();
  33. }
  34. // 连接
  35. doLink(call) {
  36. let ws = uni.connectSocket({
  37. url: this._ws,
  38. // 可选参数 设置默认值
  39. header: {
  40. 'content-type': 'application/json'
  41. },
  42. method: 'GET',
  43. success: () => {
  44. call && call()
  45. }
  46. })
  47. return ws;
  48. }
  49. doOpen() {
  50. this.socket.onOpen((ev) => {
  51. this.onOpen(ev)
  52. })
  53. this.socket.onMessage((ev) => {
  54. this.onMessage(ev)
  55. })
  56. this.socket.onClose((ev) => {
  57. this.onClose(ev)
  58. })
  59. this.socket.onError((ev) => {
  60. this.onError(ev)
  61. })
  62. }
  63. // 打开
  64. onOpen() {
  65. // 打开时重发未发出的消息
  66. let list = Object.assign([], this._msgs)
  67. list.forEach((item) => {
  68. if (this.send(item)) {
  69. let idx = this._msgs.indexOf(item)
  70. if (idx != -1) {
  71. this._msgs.splice(idx, 1)
  72. }
  73. }
  74. })
  75. }
  76. // 手动关闭
  77. doClose() {
  78. this._isLink = false
  79. this._events = {}
  80. this._msgs = []
  81. this.socket.close({
  82. success: () => {
  83. console.log('socket close success')
  84. }
  85. })
  86. }
  87. // 添加监听
  88. on(name, handler) {
  89. this.subscribe(name, handler);
  90. }
  91. // 取消监听
  92. off(name, handler) {
  93. this.unsubscribe(name, handler);
  94. }
  95. // 关闭事件
  96. onClose() {
  97. // 是否重新连接
  98. if (this._isLink) {
  99. setTimeout(() => {
  100. this.resetLink()
  101. }, 3000)
  102. }
  103. }
  104. // 错误
  105. onError(evt) {
  106. this.Notify({
  107. Event: 'error',
  108. Data: evt
  109. });
  110. }
  111. // 接受数据
  112. onMessage(evt) {
  113. try {
  114. // 解析推送的数据
  115. const data = JSON.parse(evt.data);
  116. // 通知订阅者
  117. this.Notify({
  118. Event: 'message',
  119. Data: data
  120. });
  121. } catch (err) {
  122. console.error(' >> Data parsing error:', err);
  123. // 通知订阅者
  124. this.Notify({
  125. Event: 'error',
  126. Data: err
  127. });
  128. }
  129. }
  130. // 订阅事件的方法
  131. subscribe(name, handler) {
  132. if (this._events.hasOwnProperty(name)) {
  133. this._events[name].push(handler); // 追加事件
  134. } else {
  135. this._events[name] = [handler]; // 添加事件
  136. }
  137. }
  138. // 取消订阅事件
  139. unsubscribe(name, handler) {
  140. let start = this._events[name].findIndex(item => item === handler);
  141. // 删除该事件
  142. this._events[name].splice(start, 1);
  143. }
  144. // 发布后通知订阅者
  145. Notify(entry) {
  146. // 检查是否有订阅者 返回队列
  147. const cbQueue = this._events[entry.Event];
  148. if (cbQueue && cbQueue.length) {
  149. for (let callback of cbQueue) {
  150. if (callback instanceof Function) callback(entry.Data);
  151. }
  152. }
  153. }
  154. // 发送消息
  155. send(data) {
  156. this.changeSubs(data)
  157. if (this.socket.readyState == 1) {
  158. this.socket.send({ data: JSON.stringify(data) })
  159. return true
  160. } else {
  161. // 保存到待发送信息
  162. if (!this._msgs.includes(data)) {
  163. this._msgs.push(data)
  164. };
  165. return false
  166. }
  167. }
  168. // 修改订阅列表(交易所用)
  169. changeSubs(data) {
  170. if (data.cmd == 'sub') {
  171. if (!this.subs.includes(data.msg)) {
  172. this.subs.push(data.msg)
  173. }
  174. } else if (data.cmd == 'unsub') {
  175. let idx = this.subs.indexOf(data.msg)
  176. if (idx != -1) {
  177. this.subs.splice(idx, 1)
  178. }
  179. }
  180. }
  181. // 重新订阅(交易所用)
  182. resetSub() {
  183. let list = Object.assign([], this.subs)
  184. list.forEach((item) => {
  185. this.send({
  186. cmd: 'sub',
  187. msg: item
  188. })
  189. })
  190. }
  191. }
  192. export default Ws