wsrpc.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. (function (exports) {
  2. exports.WsRpc = function () {
  3. var ctx = this
  4. this._requests = {}
  5. /**
  6. * Connect with reconnection
  7. */
  8. this.connect = function (loc) {
  9. var ws = this.ws = new window.WebSocket(loc)
  10. ws.onopen = function () {
  11. ctx._requests = {}
  12. ctx.connected = true
  13. if (ctx.onopen !== undefined) {
  14. ctx.onopen(ctx)
  15. }
  16. }
  17. ws.onmessage = function (evt) {
  18. // console.log("RCV:",evt.data)
  19. var obj = JSON.parse(evt.data)
  20. var arrObj = [].concat(obj) // if object add, if array concat
  21. for (var i = 0; i < arrObj.length; i++) {
  22. ctx.process(arrObj[i])
  23. }
  24. }
  25. ws.onerror = function () { }
  26. ws.onclose = function () {
  27. if (ctx.connected === true) {
  28. ctx.connected = false
  29. if (ctx.onclose !== undefined) {
  30. ctx.onclose(ctx)
  31. }
  32. }
  33. // Retry
  34. setTimeout(function () {
  35. ctx.connect(loc)
  36. }, 3000) // 3 seconds reconnect
  37. }
  38. }
  39. /**
  40. * Process requests
  41. */
  42. this.process = function (obj) {
  43. switch (obj.op) {
  44. case 'call':
  45. if (obj.method === undefined || this._exports[obj.method] === undefined) {
  46. // TODO: Send object to inform error
  47. return
  48. }
  49. // Send response
  50. var nparams = [].concat((data) => {
  51. var dataObj = {
  52. 'op': 'response',
  53. 'id': obj.id,
  54. 'response': data
  55. }
  56. ctx.ws.send(JSON.stringify(dataObj))
  57. }, obj.params)
  58. this._exports[obj.method].apply(this._exports[obj.method], nparams)
  59. break
  60. case 'response':
  61. ctx._requests[obj.id](obj.response)
  62. delete ctx._requests[obj.reqId]
  63. break
  64. }
  65. }
  66. /**
  67. * Call with variadic params
  68. */
  69. this.call = function (method, ...params) {
  70. // var aparam = Array.prototype.slice.call(arguments, 1)
  71. var aparam = params
  72. return new Promise(function (resolve, reject) {
  73. if (ctx.connected === false) {
  74. reject(Error('Not connected'))
  75. }
  76. var uuidStr = uuid()
  77. var callObj = {
  78. 'op': 'call',
  79. 'id': uuidStr,
  80. 'method': method,
  81. 'params': aparam
  82. }
  83. ctx._requests[uuidStr] = resolve
  84. // console.log("Sending a call:", method)
  85. ctx.ws.send(JSON.stringify(callObj)) // if error delete request
  86. })
  87. }
  88. /**
  89. * Export function, binds export methods
  90. */
  91. this.export = function (obj) {
  92. this._exports = obj
  93. }
  94. return this
  95. }
  96. function uuid () {
  97. var ret = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
  98. var r = Math.random() * 16 | 0
  99. var v = c === 'x' ? r : (r & 0x3 | 0x8)
  100. return v.toString(16)
  101. })
  102. return ret
  103. }
  104. })(typeof exports === 'undefined' ? window : exports) // Register directly to window (this)