H5调用客户端桥接

552 阅读1分钟

H5调用客户端桥接代码

//utils.js
const APP_TYPE = 'mnappbridge'  //app协议
let isAPP = true

function getIframe() {
  let appBridgeIframe = document.createElement('iframe')
  appBridgeIframe.setAttribute('id', 'appBridgeIframe')
  appBridgeIframe.style.visibility = 'invisible'
  appBridgeIframe.style.display = 'none'
  appBridgeIframe.style.height = '0'
  appBridgeIframe.style.width = '0'
  document.body.appendChild(appBridgeIframe)
  setTimeout(() => {
    document.body.removeChild(appBridgeIframe)
  }, 5000)
  return appBridgeIframe
}

let callbackList = []

const appExe = command => {
  if (isAPP) {
    return new Promise((resolve, reject) => {
      let hash = command.split('#')[1]
      let iframe = getIframe()
      if (hash) {
        let callbackid = hash.replace('#', '')
        callbackList.push({ id: callbackid, resolve: resolve, reject: reject })
      }
      iframe.contentWindow.location.replace(command)
    })
  }
  return Promise.reject('The current environment is not native APP')
}

const setPromise = response => {
  for (let index = 0; index < callbackList.length; index++) {
    if (callbackList[index].id === response.responseId) {
      response.responseData.code !== 200 ? callbackList[index].reject(response.responseData) : callbackList[index].resolve(response.responseData)
      callbackList.splice(index, 1)
      break
    }
  }
}

const callNative = (moduleApi, query) => {
  let callbackId = `function_${new Date().getTime()}`
  let schemeUrl = `${APP_TYPE}://${moduleApi}?${query}#${callbackId}`
  return new Promise((resolve, reject) => {
    appExe(schemeUrl)
      .then(res => {
        resolve(res)
      })
      .catch(err => {
        reject(err)
      })
  })
}

export { callNative, setPromise }
//main.js
import { setPromise } from './utils'
import CommonBridge from './bridge'

/** Class BridgeEventBus */
const BridgeEventBus = {
  /**
   * bind on Event.
   * @param {eventName} eventName - event callback name
   * @param {fn} fn - callback
   */
  on(eventName, fn) {
    if (!this._eventsCallbacks) {
      this._eventsCallbacks = {}
    }
    if (!this._eventsCallbacks[eventName]) {
      this._eventsCallbacks[eventName] = []
    }
    this._eventsCallbacks[eventName].push(fn)
  },
  /**
   * remove bind on Event.
   * @param {eventName} eventName - event callback name
   * @param {fn} fn - callback
   */
  remove(eventName, fn) {
    if (!this._eventsCallbacks) {
      return
    }
    if (!this._eventsCallbacks[eventName]) {
      return
    }
    let fnIndex = this._eventsCallbacks[eventName].indexOf(fn)
    while (fnIndex >= 0) {
      this._eventsCallbacks[eventName].splice(fnIndex, 1)
      fnIndex = this._eventsCallbacks[eventName].indexOf(fn)
    }
  },
  /**
   * _fire on Event.
   * @param {eventName} eventName - event callback name
   * @param {data} data - fire event data
   */
  _fire(eventName, data) {
    const eventsCallbacks = this._eventsCallbacks[eventName]
    if (eventsCallbacks) {
      for (let i = 0; i < eventsCallbacks.length; i++) {
        eventsCallbacks[i](data)
      }
    }
  }
}

if (!window.NanAppBridge) {
  window.NanAppBridge = {}
}

/**
 * function receiveFromNative
 * 端上回调方法
 */
window.NanAppBridge.receiveFromNative = function(res) {  //监听native向页面发送的消息
  try {
    let response = JSON.parse(res)
    if (response.module && response.method) {
      // 端上主动发布一些消息时,BridgeEventBus
      BridgeEventBus._fire(response.module + '/' + response.method, response.data)  // eg: response = {callbackId: "", module: "", method: "", data: {}}
    } else {
      setPromise(response)  // eg: response = {responseId:"", responseData: {code:200, message:"", data: {}}}
    }
  }catch (err) {
    console.log(err)
  }
}

export { CommonBridge, BridgeEventBus }
//bridge.js
import { callNative } from './utils'

const webviewsuccess = params => {
  let query = ''
  for (let i in params) {
    query += i + "=" + params[i] + "&";
  }
  return callNative('nativecommon/webviewsuccess', query)
}

export default { webviewsuccess }
//使用方
import { CommonBridge } from './main'
CommonBridge.webviewsuccess({
  timeout: 5000
}).then(res => {
  console.log(res)
}).catch(err => {
  console.log(err)
})