postmessage-duplexpostmessage-duplex
首页
指南
API
示例
🎮 Playground
  • FAQ
  • 更新日志
  • GitHub
  • 简体中文
  • English
GitHub
首页
指南
API
示例
🎮 Playground
  • FAQ
  • 更新日志
  • GitHub
  • 简体中文
  • English
GitHub
  • 指南

    • 介绍
    • 快速开始
    • Iframe 通讯
    • Service Worker 通讯
    • TypeScript 支持
    • 调试技巧

快速开始

本指南将帮助你在 5 分钟内上手 postmessage-duplex。

在线体验

不想安装?试试 🎮 在线 Playground - 直接在浏览器中体验所有功能!

安装

npm
npm install postmessage-duplex
yarn
yarn add postmessage-duplex
pnpm
pnpm add postmessage-duplex

CDN 使用

<script src="https://unpkg.com/postmessage-duplex/dist/index.umd.js"></script>
<script>
  const { IframeChannel, ServiceWorkerChannel } = window.PostMessageChannel
</script>

基础用法

Iframe 通讯

假设你有一个父页面需要和嵌入的 iframe 通讯。

父页面 (parent.html)

<!DOCTYPE html>
<html>
<head>
  <title>父页面</title>
</head>
<body>
  <iframe id="child" src="./child.html"></iframe>
  
  <script type="module">
    import { IframeChannel } from 'postmessage-duplex'
    
    const iframe = document.getElementById('child')
    const channel = new IframeChannel(iframe)
    
    // 发送请求到子页面
    async function getData() {
      const response = await channel.publish('getData', { id: 1 })
      console.log('收到响应:', response.data)
    }
    
    // 监听子页面的消息
    channel.subscribe('childReady', () => {
      console.log('子页面已就绪')
      return { acknowledged: true }
    })
    
    // 页面卸载时清理
    window.addEventListener('beforeunload', () => {
      channel.destroy()
    })
  </script>
</body>
</html>

子页面 (child.html)

<!DOCTYPE html>
<html>
<head>
  <title>子页面</title>
</head>
<body>
  <script type="module">
    import { IframeChannel } from 'postmessage-duplex'
    
    // 传入父页面的 origin
    const channel = new IframeChannel(window.location.origin)
    
    // 监听父页面的请求
    channel.subscribe('getData', ({ data }) => {
      console.log('收到请求:', data)
      // 返回数据给父页面
      return { name: 'test', id: data.id }
    })
    
    // 通知父页面子页面已就绪
    channel.publish('childReady', { time: Date.now() })
  </script>
</body>
</html>

Service Worker 通讯

页面端

import { ServiceWorkerChannel } from 'postmessage-duplex'

async function initSW() {
  // 一键初始化:自动注册 SW、建立连接、处理重连
  const channel = await ServiceWorkerChannel.createFromPage({
    swUrl: './sw.js',     // 自动注册 SW
    appType: 'myApp',     // 应用类型(用于按类型广播)
    appName: 'My App'     // 应用名称
  })
  
  // 发送请求
  const response = await channel.publish('fetchData', { url: '/api/data' })
  console.log('数据:', response.data)
  
  // 接收广播
  channel.onBroadcast('notification', ({ data }) => {
    console.log('收到通知:', data)
  })
}

initSW()

Service Worker 端 (sw.js)

import { ServiceWorkerChannel } from 'postmessage-duplex'

// 一行代码初始化 Hub
ServiceWorkerChannel.setupHub({ version: '1.0.0' })

// 注册处理器(所有客户端共享)
ServiceWorkerChannel.subscribeGlobal('fetchData', async ({ data }) => {
  const response = await fetch(data.url)
  return await response.json()
})

// 广播通知给所有客户端
ServiceWorkerChannel.subscribeGlobal('notifyAll', async ({ data, clientId }) => {
  const count = await ServiceWorkerChannel.broadcastToAll('notification', data, clientId)
  return { sentCount: count }
})

配置选项

const channel = new IframeChannel(iframe, {
  // 请求超时时间(毫秒),默认 5000
  timeout: 10000,
  
  // 自定义日志
  log: {
    log: console.log,
    warn: console.warn,
    error: console.error
  },
  
  // 预定义订阅
  subscribeMap: {
    'ping': () => ({ pong: true }),
    'getVersion': () => ({ version: '1.0.0' })
  }
})

错误处理

import { ReturnCode } from 'postmessage-duplex'

const response = await channel.publish('getData', { id: 1 })

switch (response.ret) {
  case ReturnCode.Success:
    console.log('成功:', response.data)
    break
  case ReturnCode.TimeOut:
    console.error('请求超时')
    break
  case ReturnCode.NoSubscribe:
    console.error('对方未订阅此事件')
    break
  case ReturnCode.ReceiverCallbackError:
    console.error('处理器错误:', response.msg)
    break
}

销毁通道

在组件卸载或页面关闭时,记得销毁通道:

// 销毁会:
// 1. 移除消息监听器
// 2. 清空订阅
// 3. 拒绝所有待处理的请求
channel.destroy()

下一步

  • Iframe 通讯详解
  • Service Worker 通讯
  • TypeScript 支持
  • 调试技巧
在 GitHub 上编辑此页
上次更新: 2026/1/31 05:17
贡献者: liquidliang, liquid, Claude
Prev
介绍
Next
Iframe 通讯