1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| type Callback = (result: any) => void;
class JSBridge { private callbacks: Map<number, { resolve: Function; reject: Function }> = new Map(); private id = 0;
call<T = any>(action: string, params?: Record<string, any>): Promise<T> { return new Promise((resolve, reject) => { const callId = ++this.id; this.callbacks.set(callId, { resolve, reject });
const message = { id: callId, action, params: params || {} };
if (window.webkit?.messageHandlers?.NativeBridge) { window.webkit.messageHandlers.NativeBridge.postMessage(message); return; }
if (window.NativeBridge) { try { const result = JSON.parse( window.NativeBridge.callNative(action, JSON.stringify(params)) ); resolve(result); } catch (e) { reject(e); } return; }
this._callViaURLScheme(action, params, callId); }); }
onNativeCallback(callId: number, result: any) { const cb = this.callbacks.get(callId); if (cb) { cb.resolve(result); this.callbacks.delete(callId); } }
onNativeEvent(event: string, data: any) { const handlers = this._eventHandlers.get(event); handlers?.forEach(h => h(data)); }
private _eventHandlers = new Map<string, Set<Function>>(); on(event: string, handler: Function) { if (!this._eventHandlers.has(event)) { this._eventHandlers.set(event, new Set()); } this._eventHandlers.get(event)!.add(handler); } off(event: string, handler: Function) { this._eventHandlers.get(event)?.delete(handler); }
private _callViaURLScheme(action: string, params: Record<string, any>, callId: number) { const url = `jsbridge://${action}?params=${encodeURIComponent(JSON.stringify(params))}&cb=${callId}`; const iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = url; document.body.appendChild(iframe); setTimeout(() => document.body.removeChild(iframe), 100); } }
export const bridge = new JSBridge();
|