reconnecting-websocket.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // MIT License:
  2. //
  3. // Copyright (c) 2010-2012, Joe Walnes
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. /**
  23. * This behaves like a WebSocket in every way, except if it fails to connect,
  24. * or it gets disconnected, it will repeatedly poll until it succesfully connects
  25. * again.
  26. *
  27. * It is API compatible, so when you have:
  28. * ws = new WebSocket('ws://....');
  29. * you can replace with:
  30. * ws = new ReconnectingWebSocket('ws://....');
  31. *
  32. * The event stream will typically look like:
  33. * onconnecting
  34. * onopen
  35. * onmessage
  36. * onmessage
  37. * onclose // lost connection
  38. * onconnecting
  39. * onopen // sometime later...
  40. * onmessage
  41. * onmessage
  42. * etc...
  43. *
  44. * It is API compatible with the standard WebSocket API.
  45. *
  46. * Latest version: https://github.com/joewalnes/reconnecting-websocket/
  47. * - Joe Walnes
  48. */
  49. export default function ReconnectingWebSocket(url, protocols) {
  50. console.log(url)
  51. protocols = protocols || []
  52. // These can be altered by calling code.
  53. this.debug = false
  54. this.reconnectInterval = 1000
  55. this.timeoutInterval = 2000
  56. var self = this
  57. var ws
  58. var forcedClose = false
  59. var timedOut = false
  60. this.url = url
  61. this.protocols = protocols
  62. this.readyState = WebSocket.CONNECTING
  63. this.URL = url // Public API
  64. this.onopen = function (event) {
  65. }
  66. this.onclose = function (event) {
  67. }
  68. this.onconnecting = function (event) {
  69. }
  70. this.onmessage = function (event) {
  71. }
  72. this.onerror = function (event) {
  73. }
  74. function connect(reconnectAttempt) {
  75. ws = new WebSocket(url, protocols)
  76. console.log(123)
  77. self.onconnecting()
  78. if (self.debug || ReconnectingWebSocket.debugAll) {
  79. console.debug('ReconnectingWebSocket', 'attempt-connect', url)
  80. }
  81. var localWs = ws
  82. var timeout = setTimeout(function () {
  83. if (self.debug || ReconnectingWebSocket.debugAll) {
  84. console.debug('ReconnectingWebSocket', 'connection-timeout', url)
  85. }
  86. timedOut = true
  87. localWs.close()
  88. timedOut = false
  89. }, self.timeoutInterval)
  90. ws.onopen = function (event) {
  91. clearTimeout(timeout)
  92. if (self.debug || ReconnectingWebSocket.debugAll) {
  93. console.debug('ReconnectingWebSocket', 'onopen', url)
  94. }
  95. self.readyState = WebSocket.OPEN
  96. reconnectAttempt = false
  97. self.onopen(event)
  98. }
  99. ws.onclose = function (event) {
  100. clearTimeout(timeout)
  101. ws = null
  102. if (forcedClose) {
  103. self.readyState = WebSocket.CLOSED
  104. self.onclose(event)
  105. } else {
  106. self.readyState = WebSocket.CONNECTING
  107. self.onconnecting()
  108. if (!reconnectAttempt && !timedOut) {
  109. if (self.debug || ReconnectingWebSocket.debugAll) {
  110. console.debug('ReconnectingWebSocket', 'onclose', url)
  111. }
  112. self.onclose(event)
  113. }
  114. setTimeout(function () {
  115. connect(true)
  116. }, self.reconnectInterval)
  117. }
  118. }
  119. ws.onmessage = function (event) {
  120. if (self.debug || ReconnectingWebSocket.debugAll) {
  121. console.debug('ReconnectingWebSocket', 'onmessage', url, event.data)
  122. }
  123. self.onmessage(event)
  124. }
  125. ws.onerror = function (event) {
  126. if (self.debug || ReconnectingWebSocket.debugAll) {
  127. console.debug('ReconnectingWebSocket', 'onerror', url, event)
  128. }
  129. self.onerror(event)
  130. }
  131. }
  132. connect(url)
  133. this.send = function (data) {
  134. if (ws) {
  135. if (self.debug || ReconnectingWebSocket.debugAll) {
  136. console.debug('ReconnectingWebSocket', 'send', url, data)
  137. }
  138. return ws.send(data)
  139. } else {
  140. throw 'INVALID_STATE_ERR : Pausing to reconnect websocket'
  141. }
  142. }
  143. this.close = function () {
  144. forcedClose = true
  145. if (ws) {
  146. ws.close()
  147. }
  148. }
  149. /**
  150. * Additional public API method to refresh the connection if still open (close, re-open).
  151. * For example, if the app suspects bad data / missed heart beats, it can try to refresh.
  152. */
  153. this.refresh = function () {
  154. if (ws) {
  155. ws.close()
  156. }
  157. }
  158. }
  159. /**
  160. * Setting this to true is the equivalent of setting all instances of ReconnectingWebSocket.debug to true.
  161. */
  162. ReconnectingWebSocket.debugAll = false