Exploring the Broadcast Channel API for cross-tab communication title. A gradient background with a JavaScript logo in the bottom-left corner and an icon representing a browser in the top-right corner.

探索用于跨标签通信的广播频道 API

作者头像Vultr阅读时间:5 分钟

广播频道 API 使不同浏览器窗口、标签、iframe 和 Web 工作器之间能够进行通信。它提供了一种简单高效的方式来同步多个上下文的浏览器中的数据和行为,从而创建更具反应性和吸引力的 Web 应用程序。

在本文中,我们将探讨广播频道 API 的概念、用法和现实世界中的应用程序。我们还将逐步介绍一个使用 API 将消息发送到不同标签和窗口的应用程序的实际示例。

了解广播频道 API

广播频道 API 引入了一种机制,使相同用户和浏览器在同一来源中的不同上下文能够相互通信。它基于创建单个共享通道的原理,多个浏览器上下文可以随时加入或离开该通道。

加入后,这些上下文可以通过该通道发送和接收消息,从而实现无缝的数据交换和事件传播。这种机制消除了对复杂服务器端通信的需求。以下是您使用 API 的简要介绍。

创建或加入通道

js
const bc = new BroadcastChannel("test_channel");

发送消息

js
bc.postMessage("This is a test message");

接收消息(有关详细信息,请参见 广播频道:消息事件

js
bc.onmessage = (event) => {
  console.log(event.data);
  // { method: "add", note: "This is a test message" }
};

构建 Node.js 应用程序

首先,请按照我们之前文章中“在 Vultr 上部署服务器”部分中的步骤部署服务器。接下来,让我们通过 SSH 访问服务器终端并为我们的 Web 应用程序设置项目。

我们将使用 Nano 文本编辑器在服务器上创建和编辑项目文件。您可以查看 快捷方式备忘单 以获取有关使用 Nano 的帮助。我们还将使用 Uncomplicated Firewall (UFW) 来控制允许进出服务器的流量。在我们的应用程序中,我们使用 Node.js 来提供应用程序的索引,并使用 http-server 运行应用程序。任何其他类型的服务器,如 Python 和 Apache,也可以用于实现相同的功能。我们还使用端口 8080 通过 UFW 仅允许通过此端口传入流量。

  1. 创建一个项目目录,并进入该目录。
    bash
    mkdir notes-app
    cd notes-app
    
  2. 初始化 Node.js 项目。
    bash
    npm init -y
    
  3. 安装 HTTP 服务器依赖项。
    bash
    npm install http-server
    
  4. 创建一个 HTML 文件。
    bash
    nano index.html
    
  5. 将以下代码复制粘贴到 index.html 文件中。
    html
    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Note-taking App</title>
        <link rel="stylesheet" href="styles.css" />
      </head>
      <body>
        <h1>Note-taking App</h1>
        <div id="noteList"></div>
        <div id="noteForm">
          <label for="noteInput">New note</label>
          <input type="text" id="noteInput" placeholder="A note..." />
          <button id="addNoteButton">Add Note</button>
          <button id="resetNoteButton">Reset Notes</button>
        </div>
        <script src="app.js"></script>
      </body>
    </html>
    
  6. 保存并退出文件。
  7. 创建一个 CSS 文件。
    bash
    nano styles.css
    
  8. 将以下代码复制粘贴到 styles.css 文件中。
    css
    body {
      font-family: Arial, sans-serif;
      background-color: #f4f4f4;
      margin: 0;
      padding: 20px;
    }
    
    h1 {
      color: #333;
      text-align: center;
    }
    
    #noteList {
      display: grid;
      row-gap: 10px;
      background-color: #fff;
      border: 1px solid #ddd;
      border-radius: 5px;
      padding: 10px;
      margin-bottom: 20px;
    }
    
    #noteList div {
      background-color: #f9f9f9;
      border: 1px solid #ddd;
      border-radius: 3px;
      padding: 10px;
    }
    
    #noteForm {
      display: grid;
      column-gap: 10px;
      align-items: center;
      grid-template-columns: max-content 1fr max-content max-content;
    }
    
    #noteInput {
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 3px;
      font-size: 16px;
    }
    
    button {
      padding: 10px 20px;
      background-color: #4caf50;
      color: #fff;
      border: none;
      border-radius: 3px;
      font-size: 16px;
      cursor: pointer;
    }
    
    button:hover {
      background-color: #45a049;
    }
    
  9. 保存并退出文件。

实现广播频道 API

  1. notes-app 目录中,创建一个 JavaScript 文件。
    bash
    nano app.js
    
  2. 将以下 JavaScript 代码复制粘贴到 app.js 中。
    js
    const noteList = document.getElementById("noteList");
    const noteInput = document.getElementById("noteInput");
    const addNoteButton = document.getElementById("addNoteButton");
    const resetNoteButton = document.getElementById("resetNoteButton");
    
    let notes = [];
    
    function renderNotes() {
      noteList.innerHTML = "";
    
      notes.forEach((note) => {
        const noteItem = document.createElement("div");
        noteItem.textContent = note;
        noteList.appendChild(noteItem);
      });
    }
    
    addNoteButton.addEventListener("click", () => {
      const newNote = noteInput.value.trim();
    
      if (newNote) {
        notes.push(newNote);
        renderNotes();
        noteInput.value = "";
    
        channel.postMessage({ action: "add", note: newNote });
      }
    });
    
    resetNoteButton.addEventListener("click", () => {
      notes = [];
      renderNotes();
    
      channel.postMessage({ action: "reset" });
    });
    
    const channel = new BroadcastChannel("notes-channel");
    
    channel.addEventListener("message", (event) => {
      const { action, note } = event.data;
    
      if (action === "add") {
        notes.push(note);
        renderNotes();
      } else if (action === "reset") {
        notes = [];
        renderNotes();
      }
    });
    
  3. 保存并退出文件。
  4. 允许传入端口 8080 的连接
    bash
    sudo ufw allow 8080
    
  5. 启动文件服务器。
    bash
    npx http-server
    
  6. 访问 http://<server-ip>:8080 上的应用程序 URL

现在,您可以并排打开两个浏览器窗口或标签页。在应用程序的一个页面上添加一个笔记,您会看到笔记出现在第二个标签页中,而无需刷新页面。尝试重置所有笔记,您会看到笔记从两个标签页中删除,而无需刷新。

让我们看看我们在 app.js 中编写的代码。renderNotes 函数为添加的每个笔记创建一个元素。addNoteButton 函数允许我们在应用程序中添加笔记,channel.postMessage 将“添加”操作广播到其他窗口或标签页。类似地,resetNoteButton 允许我们删除所有现有笔记,channel.postMessage 将“重置操作”广播到其他窗口或标签页。

最后,使用名称“notes-channel”创建一个新的 BroadcastChannel,允许共享同一来源的不同窗口/标签页之间进行通信。BroadcastChannel 的事件侦听器侦听来自该通道的 message 事件,并根据提供的输入采取措施。

现实世界中的用例和示例

  • 在新闻和媒体网站上
    • 用例:用于同步多个窗口中的文章阅读进度。
    • 示例:用户可以开始阅读文章,并在另一个窗口或标签页上从同一位置无缝地继续阅读,从而实现一致的阅读体验。
  • 在生产力应用程序中
    • 用例:用于在多个上下文之间启用文档或文件更改的实时同步。
    • 示例:在协作文本编辑器中,一个用户所做的更改可以实时广播到其他上下文。
  • 在社交媒体平台上
    • 用例:用于在多个标签页或窗口中通知用户新的更新、消息或通知。
    • 示例:如果用户为一个社交媒体平台打开了多个标签页,他们可以在所有上下文中接收实时更新,确保他们不会错过重要信息。

结论

在本文中,我们探讨了广播频道 API 的概念、用法和实际实现。我们构建了一个基本的同步笔记应用程序,并学习了如何使用广播频道 API 构建相互关联的 Web 体验。

这是一篇由 Vultr 赞助的文章。Vultr 是全球最大的私营云计算平台。Vultr 是开发人员的热门选择,已为 185 个国家/地区的 150 多万客户提供了灵活、可扩展的全球云计算、云 GPU、裸机和云存储解决方案。了解有关 Vultr 的更多信息

关注 MDN 的最新动态

订阅 MDN 时事通讯,不错过有关最新 Web 开发趋势、技巧和最佳实践的任何更新。