js_bridge

187 阅读1分钟
export default () => {
  function getOsType() {
    let ua = navigator.userAgent
    let osType
    let isIos = ua.indexOf('iPhone') > -1 || ua.indexOf('iPad') > -1
    let isAndroid = ua.indexOf('Android') > -1 || ua.indexOf('Adr') > -1
    if (isIos) {
      osType = 'IOS'
    } else if (isAndroid) {
      osType = 'ANDROID'
    } else {
      osType = 'OTHER'
    }
    return osType
  }

  function createMessage(param) {
    let { nativeMethodName, params, successCallBackID, failureCallBackID } = param
    let message = {
      methodName: nativeMethodName,
      params: params,
      successCallBackID: successCallBackID,
      failureCallBackID: failureCallBackID
    }
    return message
  }

  function postMsg(msg) {
    let osType = getOsType()
    if (window.isInNative) {
      switch (osType) {
        case 'IOS':
          window.webkit.messageHandlers.TjeEventHandler.postMessage(msg)
          break
        case 'ANDROID':
          msg = JSON.stringify(msg)
          window.AndroidTjeEventHandler.postMessage(msg)
          break
        default:
          console.log('not in android or ios')
          break
      }
    } else {
      console.log('post msg to native: ', msg)
    }
  }

  // 初始化全局TjeEventHandler对象 和 TjeBridgeEvent对象 以实现jsBridge
  window.isInNative = false // 是否存在于native应用内标识符
  if (window.webkit || window.AndroidTjeEventHandler) {
    window.isInNative = true
  }
  let callBackID = 0
  window.TjeEventHandler = {
    callNative: function(paramObj) {
      let nativeMethodName = paramObj['method']
      let params = paramObj['params'] || {}
      let successCallBack = paramObj['success']
      let failureCallBack = paramObj['error']
      callBackID++ // callBackID依次递增,保证唯一性

      let successCallBackID = successCallBack ? `${callBackID}_successCallBack` : ''
      let failureCallBackID = failureCallBack ? `${callBackID}_failureCallBack` : ''
      let msg = createMessage({
        nativeMethodName,
        params,
        successCallBackID,
        failureCallBackID
      })

      if (!window.TjeBridgeEvent._listeners[successCallBackID] && successCallBackID) {
        window.TjeBridgeEvent.addEvent(successCallBackID, data => {
          successCallBack(data)
        })
      }
      if (!window.TjeBridgeEvent._listeners[failureCallBackID] && failureCallBackID) {
        window.TjeBridgeEvent.addEvent(failureCallBackID, data => {
          failureCallBack(data)
        })
      }

      postMsg(msg)
    },

    callBack: function(callBackID, data) {
      window.TjeBridgeEvent.releaseEvent(callBackID, data)
    },
    removeAllCallBacks: function(data) {
      window.TjeBridgeEvent._listeners = {}
    }
  }
  window.TjeBridgeEvent = {
    _listeners: {},
    addEvent: function(type, fn) {
      if (typeof this._listeners[type] === 'undefined') {
        this._listeners[type] = []
      }
      if (typeof fn === 'function') {
        this._listeners[type].push(fn)
      }

      return this
    },

    releaseEvent: function(type, param) {
      let arrayEvent = this._listeners[type]
      if (arrayEvent instanceof Array) {
        for (let i = 0, length = arrayEvent.length; i < length; i += 1) {
          if (typeof arrayEvent[i] === 'function') {
            arrayEvent[i](param)
          }
        }
        // 函数调用后清空
        delete this._listeners[type]
      }

      return this
    },

    removeEvent: function(type, fn) {
      let arrayEvent = this._listeners[type]
      if (typeof type === 'string' && arrayEvent instanceof Array) {
        if (typeof fn === 'function') {
          for (let i = 0, length = arrayEvent.length; i < length; i += 1) {
            if (arrayEvent[i] === fn) {
              this._listeners[type].splice(i, 1)
              break
            }
          }
        } else {
          delete this._listeners[type]
        }
      }

      return this
    }
  }
}