使用 SharedWorker 进行跨标签通信

简介: sharedWorker 也是一种 worker,sharedWorker 的创建和 webWorker 的创建一样,使用 new 关键字来进行初始化(不能通过代码片段创建),不同的是可以在浏览器不同标签下(同源,后面的跨页面等均是在同源的前提下)使用同一个js url 创建sharedWorker 会复用同一个实例。

语法


sharedWorker 也是一种 worker,sharedWorker 的创建和 webWorker 的创建一样,使用 new 关键字来进行初始化(不能通过代码片段创建),不同的是可以在浏览器不同标签下(同源,后面的跨页面等均是在同源的前提下)使用同一个js url 创建sharedWorker 会复用同一个实例。

PS:webpack 环境下需要使用相关的 loader 加载,vite 环境直接在导入文件时添加 query 参数 import SharedWorker from './worker.js?sharedworker'

const worker = new SharedWorker('./worker.js');
worker.port.onmessage = (e) => {
  if (e.data.event === 'connected') {
    worker.port.postMessage({ event: 'init', payload: { username: 'king' } })
  }
}
复制代码

基于 sharedWorker 的这种特性,我们可以利用它来进行不同页面之间的通信,具体案例我们最后再说,先来看一下 sharedWorker 的语法。

我们所有的操作都将基于 sharedWorker 的 port 属性,这是一个 MessagePort 对象。

我们可以在 port 上执行以下操作:

  • start:激活端口,开始发送消息
  • close:断开连接
  • postMessage:发送消息,并且可以选择是否将对象的所有权转交

我们可以基于 port 的 message 和 messageerror 事件来监听消息。在绑定 message 事件的时候我们可以使用句柄的方式(onmessage)绑定,也可以使用时间监听器(addEventListener)来绑定,二者的区别在于通过句柄绑定的时候不用显式调用 start。

主线程和 worker 的区别就在于获取 port 的方式不同,在 sharedWorker 内部,我们同样基于 port 进行操作,我们可以通过 onconnect 连接到上述相同的port

/* 连接事件触发 */
self.onconnect = function (e) {
  console.log("worker内:连接事件触发");
  const port = e.ports[0];
  port.postMessage('connected')
  port.onmessage = (e) => {
    if(e.data.event === 'init') {
      // exec some code
    }
  }
}
复制代码

在 sharedWorker 内部同样遵循 webWorker 的一些限制,如 alert ,在 worker 中调用 alert 之后脚本调试器会看到报错

1682519875(1).png


调试


sharedWorker 的调试不能直接在页面的控制台中进行,需要使用浏览器提供的工具进行调试,例如在 chrome 中,可以进入 chrome://inspect/#workers来管理已经激活的 sharedWorker 实例

1682519904(1).png

点击 inspect 可以打开指定 sharedWorker 的调试工具

1682519920(1).png

点击terminate 可以销毁指定的 sharedWorker


应用


sharedWorker 的应用场景主要是跨页面的通信,例如在不同标签之间同步状态,以消息通知为例,我们在 sharedWorker 中使用 socketio-client 连接消息服务器处理消息逻辑,在 connect 时缓所有的 port,在收到消息或者某个 port 已读消息时,将事件广播到每个端口触发不同的页面事件处理,达到不同页面之间状态同步的目的。

1682519937(1).png

/* 存下与 shared worker 连接了的所有端口 */
const portPool: MessagePort[] = [];
let socket: Socket | undefined;
const _self: SharedWorkerGlobalScope = self as any;
/* 连接事件触发 */
_self.onconnect = function (e: MessageEvent) {
  // 初始化 socketIO 实例
  const port = e.ports[0];
  // 将 port 添加到 portPool 中
  portPool.push(port);
  port.postMessage({ event: "connected" });
  port.onmessage = (e: MessageEvent<{ event: string; payload: unknown }>) => {
    switch (e.data.event) {
      case "init":
        if (!socket) {
          socket = io(import.meta.env.VITE_SOCKET_NOTICE, {
            query: { token: e.data.payload },
          });
          socket.on("clientNotice", (data) => {
            // console.log("[ data ] >", data);
            broadcast({ event: "newNotice", payload: data });
          });
        } else {
          console.log("已存在 socket 实例");
        }
        break;
      case "close": {
        const index = portPool.findIndex((p) => p === port);
        // 关闭连接,移除对应 port
        portPool.splice(index, 1);
        port.close();
        break;
      }
      default:
        broadcast(e.data);
    }
  };
};
/* 向当前所有连接了的 port 广播消息 */
function broadcast(message: { event: string; payload: unknown }) {
  portPool.forEach((port) => {
    port.postMessage(message);
  });
}


相关文章
|
5月前
|
存储 前端开发 安全
跨页面通信的方式有哪些?
跨页面通信的方式有哪些?
58 0
|
3天前
|
存储 移动开发 API
本地跨页面通讯
本地跨页面通讯包括Web Storage、Cookies、Broadcast Channel API、SharedWorker和postMessage API等方法。Web Storage和Cookies用于存储数据共享,Broadcast Channel API提供消息通道,SharedWorker支持多页面共享后台线程,postMessage用于不同窗口或页面间的消息传递。根据项目需求选择合适的技术,可实现高效通信。
|
3天前
|
存储 前端开发 安全
无限连接:前端跨页面通信的实现与应用
在前端开发中,有时我们需要在不同的页面之间进行数据传递和交互。这种场景下,前端跨页面通信就显得尤为重要。前端跨页面通信是指在不同的页面之间传递数据、发送消息以及实现页面间的交互操作。本文将详细介绍前端跨页面通信的属性、应用场景以及实现方法,并提供一些代码示例和引用资料,帮助读者深入了解并应用这一重要的技术。
|
3天前
|
存储 缓存 JavaScript
跨标签页通信的8种方式(上)
跨标签页通信是指在浏览器中的不同标签页之间进行数据传递和通信的过程。在传统的Web开发中,每个标签页都是相互独立的,无法直接共享数据。然而,有时候我们需要在不同的标签页之间进行数据共享或者实现一些协同操作,这就需要使用跨标签页通信来实现。
62 0
|
3天前
|
存储 JavaScript 前端开发
跨标签页通信的8种方式(下)
跨标签页通信是指在浏览器中的不同标签页之间进行数据传递和通信的过程。在传统的Web开发中,每个标签页都是相互独立的,无法直接共享数据。然而,有时候我们需要在不同的标签页之间进行数据共享或者实现一些协同操作,这就需要使用跨标签页通信来实现。
66 0
|
3天前
|
存储 Web App开发 移动开发
跨页面通信有多少种技术方式可以实现?
跨页面通信有多少种技术方式可以实现?
76 0
|
11月前
|
存储 Web App开发 前端开发
💞💞💞SharedWorker 让你多个页面相互通信
SharedWorker 是一个新的Web Worker API,它允许你在多个页面之间共享一个Worker。 SharedWorker 代表一种特定类型的Worker,可以在多个浏览器上下文中运行,
143 0
💞💞💞SharedWorker 让你多个页面相互通信
|
12月前
如何跨场景进行交互
在讲游戏场景的时候,我通常会使用这样的类比:把游戏比作一个房子,场景就是房子里的房间,通常一个房子里有多个房间,而且每个房间都互相连通,可以从一个房间进入到另一个房间。对应的就是可以从游戏中的一个场景进入到另一个场景。
117 0
|
监控 安全 网络架构
用于同步光网络 (SONET) 和同步数字体系 (SDH) 控制的通用多协议标签交换 (GMPLS) 扩展
本文档提供了特定于同步光网络 (SONET)/同步数字体系结构 (SDH) 的详细信息。根据 [RFC3471],SONET/SDH 特定参数在信令协议中携带在流量参数特定对象中。
369 0
用于同步光网络 (SONET) 和同步数字体系 (SDH) 控制的通用多协议标签交换 (GMPLS) 扩展
|
网络协议 安全 Unix
虚拟路由和转发 (VRF) 表上下文中的多点标签分发协议带内信令
本文档是 Internet 工程任务组 (IETF) 的产品。它代表了 IETF 社区的共识。它已接受公众审查,并已获互联网工程指导小组 (IESG) 批准出版。有关 Internet 标准的更多信息,请参见 RFC 5741 的第 2 节。
373 0
虚拟路由和转发 (VRF) 表上下文中的多点标签分发协议带内信令