postMessager.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /**
  2. * Initialize a new `Emitter`.
  3. *
  4. * @api public
  5. */
  6. function Emitter (obj) {
  7. if (obj) return mixin(obj)
  8. };
  9. /**
  10. * Mixin the emitter properties.
  11. *
  12. * @param {Object} obj
  13. * @return {Object}
  14. * @api private
  15. */
  16. function mixin (obj) {
  17. for (var key in Emitter.prototype) {
  18. obj[key] = Emitter.prototype[key]
  19. }
  20. return obj
  21. }
  22. /**
  23. * Listen on the given `event` with `fn`.
  24. *
  25. * @param {String} event
  26. * @param {Function} fn
  27. * @return {Emitter}
  28. * @api public
  29. */
  30. Emitter.prototype.on =
  31. Emitter.prototype.addEventListener = function (event, fn) {
  32. this._callbacks = this._callbacks || {};
  33. (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
  34. .push(fn)
  35. return this
  36. }
  37. /**
  38. * Adds an `event` listener that will be invoked a single
  39. * time then automatically removed.
  40. *
  41. * @param {String} event
  42. * @param {Function} fn
  43. * @return {Emitter}
  44. * @api public
  45. */
  46. Emitter.prototype.once = function (event, fn) {
  47. function on () {
  48. this.off(event, on)
  49. fn.apply(this, arguments)
  50. }
  51. on.fn = fn
  52. this.on(event, on)
  53. return this
  54. }
  55. /**
  56. * Remove the given callback for `event` or all
  57. * registered callbacks.
  58. *
  59. * @param {String} event
  60. * @param {Function} fn
  61. * @return {Emitter}
  62. * @api public
  63. */
  64. Emitter.prototype.off =
  65. Emitter.prototype.removeListener =
  66. Emitter.prototype.removeAllListeners =
  67. Emitter.prototype.removeEventListener = function (event, fn) {
  68. this._callbacks = this._callbacks || {}
  69. // all
  70. if (arguments.length === 0) {
  71. this._callbacks = {}
  72. return this
  73. }
  74. // specific event
  75. var callbacks = this._callbacks['$' + event]
  76. if (!callbacks) return this
  77. // remove all handlers
  78. if (arguments.length === 1) {
  79. delete this._callbacks['$' + event]
  80. return this
  81. }
  82. // remove specific handler
  83. var cb
  84. for (var i = 0; i < callbacks.length; i++) {
  85. cb = callbacks[i]
  86. if (cb === fn || cb.fn === fn) {
  87. callbacks.splice(i, 1)
  88. break
  89. }
  90. }
  91. return this
  92. }
  93. /**
  94. * Emit `event` with the given args.
  95. *
  96. * @param {String} event
  97. * @param {Mixed} ...
  98. * @return {Emitter}
  99. */
  100. Emitter.prototype.emit = function (event) {
  101. this._callbacks = this._callbacks || {}
  102. var args = [].slice.call(arguments, 1)
  103. var callbacks = this._callbacks['$' + event]
  104. if (callbacks) {
  105. callbacks = callbacks.slice(0)
  106. for (var i = 0, len = callbacks.length; i < len; ++i) {
  107. callbacks[i].apply(this, args)
  108. }
  109. }
  110. return this
  111. }
  112. /**
  113. * Return array of callbacks for `event`.
  114. *
  115. * @param {String} event
  116. * @return {Array}
  117. * @api public
  118. */
  119. Emitter.prototype.listeners = function (event) {
  120. this._callbacks = this._callbacks || {}
  121. return this._callbacks['$' + event] || []
  122. }
  123. /**
  124. * Check if this emitter has `event` handlers.
  125. *
  126. * @param {String} event
  127. * @return {Boolean}
  128. * @api public
  129. */
  130. Emitter.prototype.hasListeners = function (event) {
  131. return !!this.listeners(event).length
  132. }
  133. // function bind (obj, fn) {
  134. // if (typeof fn === 'string') fn = obj[fn]
  135. // if (typeof fn !== 'function') throw new Error('bind() requires a function')
  136. // var args = [].slice.call(arguments, 2)
  137. // return function () {
  138. // return fn.apply(obj, args.concat([].slice.call(arguments)))
  139. // }
  140. // };
  141. /**
  142. * postMessager管理器
  143. * @param {String} target 父级源地址
  144. * @param {Object} opts postMessage配置
  145. *
  146. */
  147. function PostMessager (target = '*', opts) {
  148. if (!(this instanceof PostMessager)) {
  149. return new PostMessager(target, opts)
  150. }
  151. if (target && (typeof target === 'object')) {
  152. opts = target
  153. target = undefined
  154. }
  155. Emitter(this)
  156. opts = opts || {}
  157. opts.path = opts.path || '/'
  158. this.opts = opts
  159. this.target = target
  160. this.requestQueue = {} // 请求队列
  161. window.addEventListener('message', (event) => {
  162. this.msgHandler(event)
  163. }, false)
  164. }
  165. PostMessager.prototype.send = function (request, callback) {
  166. request.reqId = new Date().getTime()
  167. window.parent.postMessage(request, this.target)
  168. return new Promise((resolve, reject) => {
  169. this.on(`res_${request.reqId}`, (obj) => {
  170. if (obj && obj.data && obj.data.response) {
  171. resolve(obj.data.response)
  172. } else {
  173. reject(obj.data.error)
  174. }
  175. callback && callback(obj)
  176. })
  177. })
  178. }
  179. PostMessager.prototype.msgHandler = function (event) {
  180. let resId = event.data.resId
  181. if (resId) {
  182. this.emit(`res_${resId}`, event)
  183. } else {
  184. this.opts['callback'] && this.opts['callback'](event.data)
  185. }
  186. }
  187. export default PostMessager