wsrpc.js 3.1 KB

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