bridge.js

/**
 * 跨窗口消息传递
 * @module $ui/utils/bridge
 */
import Messager from './messager'

import {uid} from './util'

/**
 * 向目标发送信息
 * @param {object} options 参数对象
 * @param {string} options.bridge 目标的桥页面url地址
 * @param {string} options.channel 消息频道名称
 * @param {*} [options.data] 消息内容
 * @param {string} [options.origin] 自身的桥地址,目标可以通过桥联系到自己
 */
export function fire({bridge, channel, data, origin}) {
  return new Messager({
    bridge: bridge,
    origin: origin,
    ready(instance) {
      instance.fire(channel, data)
      setTimeout(() => {
        instance.destroy()
      }, 0)
    }
  })
}

/**
 * 接收目标发送过来的信息
 * @param channel 消息频道名称
 * @param handler 消息处理函数
 * @param opts Messager参数
 * @return {Messager}
 */
export function on(channel, handler, opts = {}) {
  const instance = new Messager(opts)
  instance.on(channel, handler)
  return instance
}

/**
 * 接收目标发送过来的信息, 只接收一次
 * @param channel 消息频道名称
 * @param handler 消息处理函数
 * @return {Messager}
 */
export function once(channel, handler) {
  const instance = on(channel, (data) => {
    handler(data)
    instance.destroy()
  })
  return instance
}

/**
 * 调用消息服务
 * @param {string} name 服务名称
 * @param {string} bridge 服务提供方的桥页面地址
 * @param {*} data 发送的数据
 * @param {string} origin 自己的桥页面地址
 * @param {function} callback 回调函数,服务提供方响应的数据通过回调返回
 *
 * @example
 *
 *   // 请求服务
 service({
        name: 'MyService',
        bridge: 'http://localhost:8001/app1/assets/bridge/index.html',
        origin: 'http://localhost:8000/assets/bridge/index.html',
        data: {
          id: '123'
        },
        callback(res) {
          console.log('服务响应信息', res)
        }
      })
 */
export function service({name, bridge, data, origin, callback}) {
  const _uid = uid()
  const postMessage = {
    uid: _uid,
    data: data
  }
  // 如果有回调,以uid为事件名称的通道接收回调数据
  if (callback) {
    const callbackId = name + _uid
    once(callbackId, message => {
      // uid匹配才触发回调
      if (message.uid === _uid) {
        callback(message.data)
      }
    })
  }
  
  fire({bridge, data: postMessage, origin, channel: name})
}

/**
 * 创建服务提供者
 * @param {string} name 服务名称
 * @param {string} origin 自己的桥页面地址
 * @param {function} handler 服务消息句柄函数,当服务被调用时触发,参数:data(调用服务传过来的数据),callback响应函数,通过回调响应给调用者
 * @return {Messager}
 *
 * @example
 *
 *  // 创建一个服务提供者
 *  const messager = provider({
        name: 'MyService',
        origin: 'http://localhost:8000/assets/bridge/index.html',
        handler: function (data, callback) {
          const response = '响应内容'
          callback(response)
        }
      })
 // 销毁
 messager.destroy()
 */
export function provider({name, origin, handler}) {
  return on(name, (message, bridge) => {
    const callbackId = name + message.uid
    const callback = (data) => {
      fire({
        bridge,
        data: {uid: message.uid, data: data},
        origin,
        channel: callbackId
      })
    }
    
    handler(message.data, callback)
  })
  
}