/** * Initialize a new `Emitter`. * * @api public */ function Emitter (obj) { if (obj) return mixin(obj) }; /** * Mixin the emitter properties. * * @param {Object} obj * @return {Object} * @api private */ function mixin (obj) { for (var key in Emitter.prototype) { obj[key] = Emitter.prototype[key] } return obj } /** * Listen on the given `event` with `fn`. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.on = Emitter.prototype.addEventListener = function (event, fn) { this._callbacks = this._callbacks || {}; (this._callbacks['$' + event] = this._callbacks['$' + event] || []) .push(fn) return this } /** * Adds an `event` listener that will be invoked a single * time then automatically removed. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.once = function (event, fn) { function on () { this.off(event, on) fn.apply(this, arguments) } on.fn = fn this.on(event, on) return this } /** * Remove the given callback for `event` or all * registered callbacks. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function (event, fn) { this._callbacks = this._callbacks || {} // all if (arguments.length === 0) { this._callbacks = {} return this } // specific event var callbacks = this._callbacks['$' + event] if (!callbacks) return this // remove all handlers if (arguments.length === 1) { delete this._callbacks['$' + event] return this } // remove specific handler var cb for (var i = 0; i < callbacks.length; i++) { cb = callbacks[i] if (cb === fn || cb.fn === fn) { callbacks.splice(i, 1) break } } return this } /** * Emit `event` with the given args. * * @param {String} event * @param {Mixed} ... * @return {Emitter} */ Emitter.prototype.emit = function (event) { this._callbacks = this._callbacks || {} var args = [].slice.call(arguments, 1) var callbacks = this._callbacks['$' + event] if (callbacks) { callbacks = callbacks.slice(0) for (var i = 0, len = callbacks.length; i < len; ++i) { callbacks[i].apply(this, args) } } return this } /** * Return array of callbacks for `event`. * * @param {String} event * @return {Array} * @api public */ Emitter.prototype.listeners = function (event) { this._callbacks = this._callbacks || {} return this._callbacks['$' + event] || [] } /** * Check if this emitter has `event` handlers. * * @param {String} event * @return {Boolean} * @api public */ Emitter.prototype.hasListeners = function (event) { return !!this.listeners(event).length } // function bind (obj, fn) { // if (typeof fn === 'string') fn = obj[fn] // if (typeof fn !== 'function') throw new Error('bind() requires a function') // var args = [].slice.call(arguments, 2) // return function () { // return fn.apply(obj, args.concat([].slice.call(arguments))) // } // }; /** * postMessager管理器 * @param {String} target 父级源地址 * @param {Object} opts postMessage配置 * */ function PostMessager (target = '*', opts) { if (!(this instanceof PostMessager)) { return new PostMessager(target, opts) } if (target && (typeof target === 'object')) { opts = target target = undefined } Emitter(this) opts = opts || {} opts.path = opts.path || '/' this.opts = opts this.target = target this.requestQueue = {} // 请求队列 window.addEventListener('message', (event) => { this.msgHandler(event) }, false) } PostMessager.prototype.send = function (request, callback) { request.reqId = new Date().getTime() window.parent.postMessage(request, this.target) return new Promise((resolve, reject) => { this.on(`res_${request.reqId}`, (obj) => { if (obj && obj.data && obj.data.response) { resolve(obj.data.response) } else { reject(obj.data.error) } callback && callback(obj) }) }) } PostMessager.prototype.msgHandler = function (event) { let resId = event.data.resId if (resId) { this.emit(`res_${resId}`, event) } else { this.opts['callback'] && this.opts['callback'](event.data) } } export default PostMessager