yumc-service-proxy
v1.0.20
Published
为 H5/Cordova、React Native 和其它非 Native 环境提供统一的服务代理。
Readme
yumc-service-proxy
为 H5/Cordova、React Native 和其它非 Native 环境提供统一的服务代理。
这个包的目标是让业务代码用同一套服务对象访问平台能力,同时把平台差异收敛到代理层:
- H5/Cordova:等待
deviceready或自定义ready后访问window[serviceName]。 - React Native:同步读取
NativeModules[serviceName]。 - 其它平台/小程序:没有 native service,统一降级为 no-op。
安装
yarn add yumc-service-proxy入口
// React Native,默认入口
import { createReadyProxy } from 'yumc-service-proxy'
// H5/Cordova
import { createReadyProxy } from 'yumc-service-proxy/h5'
// 小程序/其它非 Native 平台
import { createReadyProxy } from 'yumc-service-proxy/other'HTML Canvas 流程图
完整 H5/RN 创建代理代码流程图使用 HTML Canvas 绘制,文件在 docs/platform-flow.html。
在浏览器打开该文件可以查看 createReadyProxy / createRnProxy 内部如何合并配置、读取 native service、创建 Proxy、注册实例并返回代理对象。
H5/Cordova 用法
import { createReadyProxy } from 'yumc-service-proxy/h5'
interface RedPacketRainService {
start: (options: Record<string, unknown>) => Promise<void>
stop: () => Promise<void>
}
export const redPacketRainService = createReadyProxy<RedPacketRainService>({}, 'redPacketRainService', {
version: '1.0.0',
queueTimeout: 30000,
maxQueueSize: 300,
properties: ['start', 'stop'],
enforceMethodFilter: true,
removeFromGlobal: true
})
await redPacketRainService.canIUse('start')
await redPacketRainService.start({ scene: 'home' })H5 执行规则
createReadyProxy创建代理后立即返回服务对象。- 普通方法在
ready前调用会进入队列,ready后统一 flush。 ready默认来自 Cordovadeviceready,也可以通过options.ready自定义。ready后代理会捕获window[serviceName],并在removeFromGlobal=true时删除全局引用。- 当本地
originalService没有对应方法时,会桥接到window[serviceName][method]。 canIUse(functionName)返回Promise<boolean>,会等待ready后检查 native service。- 开启
enforceMethodFilter时,只有properties中声明的方法才可用。
React Native 用法
import { createReadyProxy } from 'yumc-service-proxy'
interface RedPacketRainService {
start: (options: Record<string, unknown>) => void
stop: () => void
}
export const redPacketRainService = createReadyProxy<RedPacketRainService>({}, 'RedPacketRainService', {
version: '1.0.0',
properties: ['start', 'stop'],
enforceMethodFilter: true,
removeFromGlobal: true
})
const available = await redPacketRainService.canIUse('start')
if (available) {
redPacketRainService.start({ scene: 'home' })
}RN 执行规则
createRnProxy创建时立即读取NativeModules[serviceName]。- 如果 native module 不存在,仍返回代理;
await service.canIUse('方法名')返回false,不会因缺少模块而在创建时抛错。 - 用户传入的
originalService会覆盖同名 native 方法,用于业务适配。 - 函数形式的
originalService仅在 native module 存在时执行,接收原始{ service };模块缺失时跳过初始化。对象形式的本地方法仍保留,但不会被canIUse识别为 native 能力。 - 调用原生方法前应先
await canIUse('方法名');不存在且没有本地覆盖的方法仍为undefined。 removeFromGlobal=true时会从NativeModules删除原始模块引用,强制业务走代理。canIUse(functionName)返回Promise<boolean>,不等待 ready。- RN 的
canIUse只检查NativeModules[serviceName]本体,不检查用户覆盖后的方法。 - 开启
enforceMethodFilter时,native 方法也必须在properties中才可用。
小程序/其它平台用法
import { createReadyProxy } from 'yumc-service-proxy/other'
interface RedPacketRainService {
start: (options: Record<string, unknown>) => void
stop: () => void
}
export const redPacketRainService = createReadyProxy<RedPacketRainService>({}, 'RedPacketRainService', { version: '1.0.0' })
await redPacketRainService.canIUse('start') // false
redPacketRainService.start({ scene: 'home' }) // no-op其它平台执行规则
- 不访问
window。 - 不访问
NativeModules。 canIUse(functionName)永远返回Promise<false>。- 任意业务方法都返回空函数,调用后返回
undefined。
跨平台封装建议
import type { ProxiedService } from 'yumc-service-proxy'
interface RedPacketRainService {
start: (options: Record<string, unknown>) => Promise<void> | void
stop: () => Promise<void> | void
}
let redPacketRainService: ProxiedService<RedPacketRainService>
if (process.env.TARO_ENV === 'h5') {
const { createReadyProxy } = await import('yumc-service-proxy/h5')
} else if (process.env.TARO_ENV === 'rn') {
const { createReadyProxy } = await import('yumc-service-proxy')
} else {
const { createReadyProxy } = await import('yumc-service-proxy/other')
}
redPacketRainService = createReadyProxy<RedPacketRainService>({}, 'RedPacketRainService')
export { redPacketRainService }API
createReadyProxy<T>(service, serviceName, options?)
H5/Cordova 入口和其它平台入口都使用这个函数名,但行为不同:
yumc-service-proxy/h5:等待 ready,桥接window[serviceName]。yumc-service-proxy/other:不访问 native,全部降级。- React Native 入口,读取
NativeModules[serviceName]并创建代理。
ProxyOptions
export interface ProxyOptions {
queueTimeout?: number
debug?: boolean
maxQueueSize?: number
ready?: Promise<void>
version?: string
properties?: string[]
parameter?: {
h5?: Record<string, { sc?: number } | undefined>
rn?: Record<string, { sc?: number } | undefined>
}
enforceMethodFilter?: boolean
removeFromGlobal?: boolean
}ProxiedService<T>
export type ProxiedService<T> = T & {
name: string
version: string
canIUse(functionName: string): Promise<boolean>
}canIUse 语义
H5/Cordova:
- 检查对象:
nativeServiceRef || window[serviceName] - 是否等待 ready:是
- 白名单规则:开启
enforceMethodFilter时必须命中properties - 返回值:
Promise<boolean>
React Native:
- 检查对象:
NativeModules[serviceName] - 是否等待 ready:否
- 白名单规则:开启
enforceMethodFilter时必须命中properties - 返回值:
Promise<boolean>
其它/小程序:
- 检查对象:无 native service
- 是否等待 ready:否
- 白名单规则:不适用
- 返回值:
Promise<false>
License
MIT
