Appearance

DSBridge - H5与Native高效通信的跨端解决方案

zhaoyifan2025-03-17frontEnd跨端通信 H5 Native JavaScript

什么是 DSBridge

DSBridge 是一个现代化的 JavaScript 桥接库,用于实现 H5 与 Native(iOS/Android)之间的双向通信。它提供了同步调用、异步调用、进度回调等多种通信方式,是目前业界较为成熟的跨端通信解决方案之一。

为什么选择 DSBridge

传统方案的痛点

在使用传统的 WebView 通信方案时,我们经常会遇到以下问题:

  • 异步问题:JavaScript 无法同步获取 Native 返回值
  • 类型转换复杂:参数和返回值需要手动序列化和反序列化
  • 调试困难:缺少统一的错误处理和日志追踪
  • API 不统一:iOS 和 Android 需要使用不同的调用方式

DSBridge 的优势

  • 同步调用支持:支持同步获取 Native 返回值
  • 类型安全:自动处理数据序列化和反序列化
  • 进度回调:支持 Native 向 H5 返回多次进度信息
  • 跨平台统一:iOS 和 Android 使用相同的 API
  • 命名空间:避免方法名冲突
  • 调试友好:内置调试模式

安装

npm install dsbridge
# 或
yarn add dsbridge

基本使用

H5 端调用 Native

import dsBridge from 'dsbridge'

// 1. 异步调用(推荐)
dsBridge.call('getUserInfo', { userId: '123' }, (data) => {
  console.log('用户信息:', data)
})

// 2. 同步调用(谨慎使用,会阻塞主线程)
const result = dsBridge.call('getToken')
console.log('Token:', result)

// 3. 使用命名空间
dsBridge.call('user.login', {
  username: 'admin',
  password: '123456'
}, (res) => {
  if (res.success) {
    console.log('登录成功')
  }
})

Native 调用 H5

// H5 端注册方法供 Native 调用
dsBridge.register('updateUserInfo', (data) => {
  console.log('收到 Native 推送的用户信息:', data)
  // 更新页面数据
  updateUI(data)
  // 返回处理结果给 Native
  return { success: true }
})

// 使用命名空间注册
dsBridge.register('app.onResume', () => {
  console.log('应用从后台恢复')
  // 刷新页面数据
  refreshData()
})

进阶使用

进度回调

当 Native 执行耗时操作时,可以多次回调 H5 报告进度:

dsBridge.call('downloadFile', {
  url: 'https://example.com/large-file.zip'
}, (progress) => {
  if (progress.status === 'downloading') {
    // 更新进度条
    updateProgress(progress.percent)
  } else if (progress.status === 'complete') {
    console.log('下载完成:', progress.filePath)
  } else if (progress.status === 'error') {
    console.error('下载失败:', progress.message)
  }
})

判断方法是否存在

// 检查 Native 是否实现了某个方法
if (dsBridge.hasNativeMethod('scanQRCode')) {
  dsBridge.call('scanQRCode', {}, (result) => {
    console.log('扫码结果:', result)
  })
} else {
  // 降级方案:使用 H5 扫码库
  useH5QRCodeScanner()
}

设置调试模式

// 开启调试模式,会打印所有通信日志
dsBridge.setDebug(true)

实际应用场景

1. 获取设备信息

// 获取设备信息
dsBridge.call('device.getInfo', {}, (info) => {
  console.log('设备信息:', {
    platform: info.platform,    // 'iOS' | 'Android'
    version: info.version,      // 系统版本
    appVersion: info.appVersion // APP 版本
  })
})

2. 调用原生能力

// 调用相机
dsBridge.call('camera.takePicture', {
  quality: 0.8,
  maxWidth: 1080
}, (result) => {
  if (result.success) {
    displayImage(result.imageUrl)
  }
})

// 调用定位
dsBridge.call('location.getCurrentPosition', {}, (position) => {
  console.log('当前位置:', position.latitude, position.longitude)
})

// 扫描二维码
dsBridge.call('scanQRCode', {}, (result) => {
  if (result.text) {
    handleQRCodeResult(result.text)
  }
})

3. 原生分享

// 分享内容
dsBridge.call('share.toFriend', {
  title: '文章标题',
  desc: '文章描述',
  imageUrl: 'https://example.com/image.jpg',
  link: 'https://example.com/article/123'
}, (res) => {
  if (res.success) {
    toast('分享成功')
  }
})

4. 页面跳转

// 跳转到原生页面
dsBridge.call('navigation.push', {
  page: 'UserProfilePage',
  params: { userId: '123' }
})

// 关闭当前 WebView
dsBridge.call('navigation.close', {})

最佳实践

1. 封装统一的调用方法

// utils/bridge.js
import dsBridge from 'dsbridge'

export const bridge = {
  // 异步调用
  callAsync(method, params = {}) {
    return new Promise((resolve, reject) => {
      if (!dsBridge.hasNativeMethod(method)) {
        reject(new Error(`Native 方法 ${method} 不存在`))
        return
      }

      dsBridge.call(method, params, (res) => {
        if (res.error) {
          reject(new Error(res.error))
        } else {
          resolve(res.data || res)
        }
      })
    })
  },

  // 同步调用
  callSync(method, params = {}) {
    if (!dsBridge.hasNativeMethod(method)) {
      console.warn(`Native 方法 ${method} 不存在`)
      return null
    }
    return dsBridge.call(method, params)
  },

  // 注册方法
  register(method, handler) {
    dsBridge.register(method, handler)
  }
}

// 使用示例
bridge.callAsync('getUserInfo', { userId: '123' })
  .then(data => {
    console.log('用户信息:', data)
  })
  .catch(err => {
    console.error('获取失败:', err)
  })

2. 类型定义(TypeScript)

// types/bridge.d.ts
interface BridgeResponse<T = any> {
  success: boolean
  data?: T
  error?: string
}

interface UserInfo {
  id: string
  name: string
  avatar: string
}

// 定义所有 Native 方法
interface NativeMethods {
  getUserInfo(params: { userId: string }): Promise<UserInfo>
  getToken(): string
  scanQRCode(): Promise<{ text: string }>
  // ...
}

3. 错误处理

// 统一错误处理
const callNative = async (method, params) => {
  try {
    // 检查是否在 APP 环境
    if (!window.dsBridge) {
      console.warn('不在 APP 环境中')
      return null
    }

    // 检查方法是否存在
    if (!dsBridge.hasNativeMethod(method)) {
      console.warn(`Native 方法 ${method} 未实现`)
      return null
    }

    // 调用方法
    return await bridge.callAsync(method, params)
  } catch (error) {
    console.error(`调用 Native 方法失败: ${method}`, error)
    // 上报错误
    reportError(error)
    return null
  }
}

4. 环境判断

// utils/env.js
export const isInApp = () => {
  return !!window.dsBridge
}

export const isIOS = () => {
  return isInApp() && /iPhone|iPad|iPod/i.test(navigator.userAgent)
}

export const isAndroid = () => {
  return isInApp() && /Android/i.test(navigator.userAgent)
}

// 使用
if (isInApp()) {
  // 在 APP 中使用 Native 能力
  dsBridge.call('getLocation')
} else {
  // 在浏览器中使用 H5 能力
  navigator.geolocation.getCurrentPosition()
}

常见问题

1. 调用无响应

  • 检查 Native 端是否正确注册了方法
  • 确认方法名和命名空间是否正确
  • 使用 hasNativeMethod 检查方法是否存在
  • 开启调试模式查看日志

2. 参数传递问题

  • DSBridge 会自动序列化 JSON,无需手动转换
  • 避免传递函数、循环引用等无法序列化的数据
  • 大数据量建议使用进度回调分批传输

3. 同步调用阻塞

  • 同步调用会阻塞 JavaScript 主线程,谨慎使用
  • 优先使用异步调用
  • 仅在获取简单数据(如 token)时使用同步调用

总结

DSBridge 是一个强大而灵活的跨端通信解决方案,它极大地简化了 H5 与 Native 之间的交互。通过合理使用 DSBridge,我们可以:

  • 充分利用 Native 能力,提升用户体验
  • 统一 iOS 和 Android 的调用方式,降低维护成本
  • 使用进度回调处理复杂的异步操作
  • 通过命名空间组织代码,提高可维护性

在实际项目中,建议结合业务需求进行二次封装,统一错误处理和类型定义,让跨端通信更加健壮和易用。

相关资源

官方仓库

官方文档

作者相关文章

其他资源

  • 作者:wendux(也是 Fly.js、dio.js 等项目的作者)
  • 相关项目Fly.jsopen in new window - 支持所有 JavaScript 运行环境的请求库
Last Updated 11/11/2025, 2:11:46 AM