lepont
Version:
A native <-> browser (webview) bridge library for react-native
100 lines (86 loc) • 2.29 kB
text/typescript
import { Message, BridgePayload, BridgeResultPayload } from './types'
import { EventEmitter } from 'events'
let cnt = 0
/**
* Returns an unique id.
*/
function uniqId(): number {
return cnt++
}
class Bridge extends EventEmitter {
resolverTable: {
[key: string]: [(arg0: any) => void, (arg0: any) => void]
} = {}
recv<T, S>(p: BridgePayload<T, S>) {
const type = p.type
switch (p.type) {
case 'result':
this.onResult(p)
break
case 'event':
this.onEvent(p.message)
break
default:
throw new Error(`Unknown bridge payload type ${type}`)
}
}
/**
* Handles the message from the webview.
*/
onEvent<T>({ type, payload }: Message<T>): void {
this.emit(type, payload)
}
/**
* Handles the result from the webview's BridgeHandler.
*/
onResult<T>(resPayload: BridgeResultPayload<T>): void {
const { id, message, error } = resPayload
const resolver = this.resolverTable[id]
if (!resolver) {
console.error(`Resolver for id=${id} not found.`)
return
}
delete this.resolverTable[id]
const [resolve, reject] = resolver
if (error) {
reject(new Error(error.message))
} else {
const { type, payload } = message
resolve(payload)
}
}
/**
* Sends a message to webview's bridge handler.
*/
async sendMessage<T, S>(message: Message<S>): Promise<T> {
const id = uniqId()
;(window as any).ReactNativeWebView.postMessage(
JSON.stringify({
id,
message
})
)
return new Promise<T>((resolve, reject) => {
this.resolverTable[id] = [resolve, reject]
})
}
}
const bridge = new Bridge()
export function sendMessage<T, S>(m: Message<S>): Promise<T> {
return bridge.sendMessage<T, S>(m)
}
export function on(type: string, cb: (arg0: any) => void) {
return bridge.on(type, cb)
}
export function off(type: string, cb: (arg0: any) => void) {
return bridge.off(type, cb)
}
Object.assign(window, { LePont: bridge })
export function checkEnvironment(w: any = window): void {
if (typeof w.ReactNativeWebView === 'undefined') {
throw new Error(
'ReactNativeWebView is undefined. Did you set onMessage of WebView?'
)
}
}
setTimeout(checkEnvironment, 300)