wsrpc.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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. var dataObj = { 'op': 'response', 'id': obj.id, 'error': 'Method not found' }
  47. ctx.ws.send(JSON.stringify(dataObj))
  48. return
  49. }
  50. // Send response
  51. var nparams = [].concat(function (data) {
  52. var dataObj = {
  53. 'op': 'response',
  54. 'id': obj.id,
  55. 'response': data
  56. }
  57. ctx.ws.send(JSON.stringify(dataObj))
  58. }, obj.params)
  59. this._exports[obj.method].apply(this._exports[obj.method], nparams)
  60. break
  61. case 'response':
  62. ctx._requests[obj.id](obj.response, obj.error)
  63. delete ctx._requests[obj.reqId]
  64. break
  65. }
  66. }
  67. /**
  68. * Call with variadic params
  69. */
  70. this.call = function (method) {
  71. var aparam = Array.prototype.slice.call(arguments, 1)
  72. // var aparam = params
  73. return new Promise(function (resolve, reject) {
  74. if (ctx.connected === false) {
  75. reject(Error('Not connected'))
  76. }
  77. var uuidStr = uuid()
  78. var callObj = {
  79. 'op': 'call',
  80. 'id': uuidStr,
  81. 'method': method,
  82. 'params': aparam
  83. }
  84. ctx._requests[uuidStr] = (res,err) => {
  85. if (err !== undefined) {
  86. reject(err)
  87. return
  88. }
  89. resolve(res)
  90. }
  91. // console.log("Sending a call:", method)
  92. ctx.ws.send(JSON.stringify(callObj)) // if error delete request
  93. })
  94. }
  95. /**
  96. * Export function, binds export methods
  97. */
  98. this.export = function (obj) {
  99. this._exports = obj
  100. }
  101. return this
  102. }
  103. function uuid () {
  104. var ret = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
  105. var r = Math.random() * 16 | 0
  106. var v = c === 'x' ? r : (r & 0x3 | 0x8)
  107. return v.toString(16)
  108. })
  109. return ret
  110. }
  111. })(typeof exports === 'undefined' ? window : exports) // Register directly to window (this)