基于订阅-发布 模式封装H5与客户端通信jsBridge的promise实现

417 阅读1分钟

核心代码 pubSub.js

 class PubSub {
  constructor() {
    this.handles = {}
  }

  on(type, handle) {
    if (!this.handles[type]) {
      this.handles[type] = []
    }
    this.handles[type].push(handle)
  }
  emit() {
    //通过传入参数获取事件类型
    //将arguments转为真数组
    var type = Array.prototype.shift.call(arguments)
    if (!this.handles[type]) {
      return false
    }
    for (var i = 0; i < this.handles[type].length; i++) {
      var handle = this.handles[type][i] //执行事件
      handle.apply(this, arguments)
    }
  }
  off(type, handle) {
    let handles = this.handles[type]
    if (!handle) {
      handles.length = 0 //清空数组
    } else {
      for (var i = 0; i < handles.length; i++) {
        var _handle = handles[i]
        if (_handle === handle) {
          //从数组中删除
          handles.splice(i, 1)
        }
      }
    }
  }
}

export default new PubSub()

H5调用原生功能封装


/**
 * @method jsBridge  H5调用原生功能,
 * @param {type:原生功能名,),...} data
 * @returns  返回Promise
 *
 * @example  jsBridge({type:'ocr_live'}).then((res)=>console.log(res))
 *
 * @description  订阅-发布模式   h5调用原生方法时根据type订阅一个事件, 原生调用H5时发布该type事件,进入订阅回调,返回promise,then方法处理业务
 */
 
 export function jsBridge(data) {
  return new Promise((resolve, reject) => {
    let toNative
    if (navigator.userAgent.includes('Android')) {
      toNative = JSON.stringify(data)
      console.log('<-----toNative--->', toNative)
      try {
        jsBridge && jsBridge.WebViewFunctionBridge(toNative)//安卓bridge 客户端提供
      } catch (error) {
        reject("不在Android壳子里")
      }
    } else {
      toNative = data
      window.webkit.messageHandlers.XYFWebViewFunctionBridge.postMessage(
          toNative
        )//ios bridge 客户端提供
    }
    // PubSub订阅type事件   
    pubSub.on(data.type, (res) => {
      resolve(res)
      pubSub.off(data.type)
    })
  })
}
 

客户端注入H5方法回调

window.nativeCallBack = (data) => {
  
  let resData = typeof data === 'object' ? data : JSON.parse(data)
  
  // 发布type事件,触发订阅type事件
  pubSub.emit(resData.type, resData)
}

业务页面调用

jsBridge({
  type: 'h5_get_device_id',
}).then((res) => {
  console.log('获取到app 回调--->', res)
})