MessageChannel和 BroadcastChannel

424 阅读2分钟

MessageChannelBroadcastChannel 是两种用于在不同浏览器上下文(如不同的浏览器窗口、标签页、iframe 等)之间进行通信的 API。它们在现代 Web 开发中非常有用,尤其是在构建复杂的单页应用程序(SPA)或需要跨页面通信的应用程序时。

MessageChannel

MessageChannel 提供了一个简单的双向通信通道,可以在同一页面的不同上下文之间传递消息。

使用场景
  • 同一页面的不同 iframe 之间通信
  • Web Worker 与主线程之间通信
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>MessageChannel Example</title>
</head>
<body>
  <iframe id="iframe1" src="iframe1.html"></iframe>
  <iframe id="iframe2" src="iframe2.html"></iframe>

  <script>
    // 创建一个新的MessageChannel
    const channel = new MessageChannel();

    // 获取iframe元素
    const iframe1 = document.getElementById('iframe1');
    const iframe2 = document.getElementById('iframe2');

    // 将MessageChannel的port1发送到iframe1
    iframe1.onload = () => {
      iframe1.contentWindow.postMessage('port1', '*', [channel.port1]);
    };

    // 将MessageChannel的port2发送到iframe2
    iframe2.onload = () => {
      iframe2.contentWindow.postMessage('port2', '*', [channel.port2]);
    };
  </script>
</body>
</html>

iframe1.htmliframe2.html 的代码如下:

<!-- iframe1.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Iframe 1</title>
</head>
<body>
  <script>
    window.addEventListener('message', (event) => {
      if (event.data === 'port1') {
        const port = event.ports[0];
        port.onmessage = (e) => {
          console.log('Message received in iframe1:', e.data);
        };
        port.postMessage('Hello from iframe1');
      }
    });
  </script>
</body>
</html>
<!-- iframe2.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Iframe 2</title>
</head>
<body>
  <script>
    window.addEventListener('message', (event) => {
      if (event.data === 'port2') {
        const port = event.ports[0];
        port.onmessage = (e) => {
          console.log('Message received in iframe2:', e.data);
        };
        port.postMessage('Hello from iframe2');
      }
    });
  </script>
</body>
</html>

BroadcastChannel

BroadcastChannel 提供了一个简单的发布-订阅模式的通信通道,可以在不同的浏览器上下文之间广播消息。

使用场景
  • 不同标签页之间的通信
  • 同一页面的不同 iframe 之间的通信
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>BroadcastChannel Example</title>
</head>
<body>
  <button id="sendMessage">Send Message</button>

  <script>
    // 创建一个新的BroadcastChannel
    const channel = new BroadcastChannel('test_channel');

    // 监听消息
    channel.onmessage = (event) => {
      console.log('Message received:', event.data);
    };

    // 发送消息
    document.getElementById('sendMessage').addEventListener('click', () => {
      channel.postMessage('Hello from main page');
    });
  </script>
</body>
</html>
在不同的标签页中使用

你可以在另一个标签页中打开相同的 HTML 文件,并会看到两者之间可以通过 BroadcastChannel 进行通信。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>BroadcastChannel Example</title>
</head>
<body>
  <button id="sendMessage">Send Message</button>

  <script>
    // 创建一个新的BroadcastChannel
    const channel = new BroadcastChannel('test_channel');

    // 监听消息
    channel.onmessage = (event) => {
      console.log('Message received:', event.data);
    };

    // 发送消息
    document.getElementById('sendMessage').addEventListener('click', () => {
      channel.postMessage('Hello from another page');
    });
  </script>
</body>
</html>
  • MessageChannel 适用于同一页面内的不同上下文(如 iframe 和 Web Worker)之间的双向通信。
  • BroadcastChannel 适用于不同浏览器上下文(如不同的标签页或 iframe)之间的广播通信。

这两种 API 都非常强大,可以根据具体需求选择合适的通信方式。