Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: taro同步方法支持缓存,并且支持外部注册和扩展 #15599

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 11 additions & 2 deletions packages/taro-platform-harmony-hybrid/src/api/apis/NativeApi.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { NativeDataChangeListener, SyncCacheProxyHandler } from './NativeApiSyncCacheProxy'
// @ts-ignore
const syncAndRelease = window.MethodChannel && window.MethodChannel.jsBridgeMode({ isAsync: false, autoRelease: true }) || (target => target)
// @ts-ignore
Expand All @@ -8,7 +9,14 @@ const asyncAndRelease = window.MethodChannel && window.MethodChannel.jsBridgeMod
const asyncAndNotRelease = window.MethodChannel && window.MethodChannel.jsBridgeMode({ isAsync: true, autoRelease: false }) || (target => target)

// export let judgeUseAxios = false
class NativeApi {
export class NativeApi {
// @ts-ignore
@(syncAndNotRelease)
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
registerNativeListener (listener: NativeDataChangeListener | null): void {
}

// @ts-ignore
@(syncAndRelease)
getWindowInfo (): any {
Expand Down Expand Up @@ -904,5 +912,6 @@ class AsyncToSyncProxy {
// }

const nativeApi = new NativeApi()
const native = new Proxy(nativeApi, new CacheStorageProxy(nativeApi)) // 第一个false是默认走jsb,true是走纯js, 第二个false是不走osChannel
const cacheNativeApi = new Proxy(nativeApi, new SyncCacheProxyHandler(nativeApi))
const native = new Proxy(cacheNativeApi, new CacheStorageProxy(cacheNativeApi)) // 第一个false是默认走jsb,true是走纯js, 第二个false是不走osChannel
export default native
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { NativeApi } from './NativeApi'

export class NativeDataCache {
private cache = new Map<string, any>()

keys (): string[] {
return Array.from(this.cache.keys())
}

set (key: string, value: any) {
this.cache.set(key, value)
}

get (key: string) {
return this.cache.get(key)
}

delete (key: string): boolean {
return this.cache.delete(key)
}

has (key: string): boolean {
return this.cache.has(key)
}
}

/**
* 系统数据更新监听器
*/
export interface NativeDataChangeListener {
/**
* 更新
* @param methodName 要更新的方法名
* @param methodArgs 要更新的方法参数,如果是空参,直接传[]
*/
change: (methodName: string, methodArgs: any[]) => void
/**
* 注册
* @param methodName 要注册的方法名
*/
register: (methodName: string) => void
/**
* 解注册
* @param methodName 要解注册的方法名
*/
unregister:(methodName: string) => void

}

/**
* 同步数据缓存ProxyHandler
*/
export class SyncCacheProxyHandler {
private readonly nativeApi: NativeApi
private listener: NativeDataChangeListener | null = null
private readonly cache: NativeDataCache
private enableMethodNames: Set<string> = new Set<string>()

constructor (nativeApi: NativeApi) {
this.nativeApi = nativeApi
this.cache = new NativeDataCache()
// 绑定类的this到self变量
const self = this
this.on({
register (methodName: string): void {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

改为支持数组,减少通信次数

self.enableMethodNames.add(methodName)
},
unregister (methodName: string): void {
self.enableMethodNames.delete(methodName)
},
change (methodName: string, methodArgs: any[]): void {
if (self.enableMethodNames.has(methodName)) {
self.updateNativeData(self.cache, methodName, methodArgs)
}
}
})
}

/**
* 监听Native数据变化
* @param listener 监听器
*/
on (listener: NativeDataChangeListener) {
this.listener = listener
this.nativeApi.registerNativeListener(this.listener)
}

/**
* 更新Native数据
* @param cache 缓存数据
* @param methodName 要更新的方法名
* @param methodArgs 要更新的方法参数
*/
updateNativeData (cache: NativeDataCache, methodName: string, methodArgs: any[]) {
const cacheKey = this.generateCacheKey(methodName, methodArgs)
// 删除该key对应的数据
cache.delete(cacheKey)
// 获取到methodName对应的方法
const fun = (this.nativeApi as any)[methodName] as (...args: any[]) => any
// 方法存在,可以安全调用,并传入参数
if (typeof fun === 'function') {
const result = fun(...methodArgs)
// 结果存入缓存
if (result) {
this.cache.set(cacheKey, result)
}
}
}

/**
* 生成cache的存储key
* @param methodName 方法名
* @param methodArgs 方法参数
*/
generateCacheKey (methodName: string, methodArgs: any[]): string {
return `${methodName}_${JSON.stringify(methodArgs)}`
}

get (target: NativeApi, propKey: string | symbol, receiver: any) {
const origMethod = Reflect.get(target, propKey, receiver)
const methodName = `${String(propKey)}`
if (typeof origMethod === 'function' && this.enableMethodNames.has(methodName)) {
return (...args: any[]) => {
const cacheKey = this.generateCacheKey(`${String(propKey)}`, args)
if (this.cache.has(cacheKey)) {
return this.cache.get(cacheKey)
} else {
const result = origMethod.apply(target, args)
if (result) {
// 有效值才存入,null或者undefined存入cache没有意义
this.cache.set(cacheKey, result)
}
return result
}
}
}
return origMethod
}
}