UNPKG

@ticatec/iframe-message-bridge

Version:

A lightweight TypeScript library for reliable communication between parent window and multiple iframes using postMessage, supporting one-way messages, request-response patterns, broadcast messaging, timeout handling, and automatic resource cleanup.

125 lines (124 loc) 4.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MessageBridgeManager = void 0; class MessageBridgeManager { constructor() { this.handlers = new Map(); this.broadcastHandlers = new Map(); this.boundHandleMessage = this.handleMessage.bind(this); window.addEventListener('message', this.boundHandleMessage); } async handleMessage(event) { const { data, source, origin } = event; if (!data || data.__bridge__ !== true) return; // 处理请求-响应消息 if (data.type === 'request') { const { requestId, eventName, data: requestData } = data; const handler = this.handlers.get(eventName); if (!handler) return; try { const result = await handler(requestData, source, origin); // 只有当 requestId 不为 null 时才发送响应 if (requestId !== null) { const response = { __bridge__: true, type: 'response', requestId, result, }; // @ts-ignore source === null || source === void 0 ? void 0 : source.postMessage(response, origin); } } catch (err) { // 只有当 requestId 不为 null 时才发送错误响应 if (requestId !== null) { const response = { __bridge__: true, type: 'response', requestId, error: err.message || String(err), }; // @ts-ignore source === null || source === void 0 ? void 0 : source.postMessage(response, origin); } } } // 处理广播消息 if (data.type === 'broadcast') { const { eventName, data: broadcastData } = data; const handler = this.broadcastHandlers.get(eventName); if (handler) { handler(broadcastData); } } } // 原有的请求-响应处理器注册 on(eventName, handler) { this.handlers.set(eventName, handler); } // 注册广播消息处理器 onBroadcast(eventName, handler) { this.broadcastHandlers.set(eventName, handler); } // 注销请求-响应处理器 off(eventName) { this.handlers.delete(eventName); } // 注销广播消息处理器 offBroadcast(eventName) { this.broadcastHandlers.delete(eventName); } // 清空所有请求-响应处理器 clearHandlers() { this.handlers.clear(); } // 清空所有广播消息处理器 clearBroadcastHandlers() { this.broadcastHandlers.clear(); } // 销毁实例,移除全局监听器 destroy() { window.removeEventListener('message', this.boundHandleMessage); this.handlers.clear(); this.broadcastHandlers.clear(); } // 自动获取所有iframe窗口 getAllIframes() { const iframes = document.querySelectorAll('iframe'); const iframeWindows = []; iframes.forEach(iframe => { try { if (iframe.contentWindow) { iframeWindows.push(iframe.contentWindow); } } catch (error) { // 跨域iframe可能无法访问contentWindow,但仍可以发送消息 console.warn('Cannot access iframe contentWindow (may be cross-origin):', error); } }); return iframeWindows; } // 向所有iframe广播消息 broadcast(eventName, data, targetOrigin = '*') { const message = { __bridge__: true, type: 'broadcast', eventName, data, }; const iframeWindows = this.getAllIframes(); iframeWindows.forEach(iframeWindow => { try { iframeWindow.postMessage(message, targetOrigin); } catch (error) { console.warn('Failed to send broadcast message to iframe:', error); } }); } } exports.MessageBridgeManager = MessageBridgeManager;