跳到主要内容

认识

2024年02月07日
柏拉文
越努力,越幸运

一、认识


SharedWorker 接口代表一种特定类型的 Worker,可以从几个浏览上下文中访问,例如几个窗口、iframe 或其他 worker。它们实现一个不同于普通 worker 的接口,具有不同的全局作用域。 如果要使 SharedWorker 连接到多个不同的页面,这些页面必须是同源的(相同的协议、host 以及端口)。它允许同一源(同协议、域名和端口)下的多个浏览上下文(例如不同的标签页、iframeservice)共享同一个 Worker 实例。这种特性使得它适合跨页面共享状态或进行多页面间通信。主线程与 Shared Worker 的通信基于 MessagePort,允许双向消息传递。主线程通过 worker.port.postMessage()Worker 发送消息。Worker 接收到消息后,可以通过 port.postMessage() 回复。 Shared Worker 中维护了多个连接的端口,每个连接可以互相广播消息,充当多页面通信的桥梁。只要至少有一个浏览上下文与 Shared Worker 保持连接,Shared Worker 就会持续运行。Worker 中的数据可以在多个页面关闭后继续存在,直到最后一个页面断开连接。和 Web Worker 一样,Shared Worker 无法直接访问 DOM 或操作页面元素。Shared Worker 只能在同一源下共享,跨域无法共享实例。

二、语法


var myWorker = new SharedWorker(aURL, name);
var myWorker = new SharedWorker(aURL, options);
  • aURL: 一个代表了 worker 将执行的脚本 URLDOMString,它必须遵守同源策略。如果 URL 的语法无效或者违反了同源策略会抛出 SECURITY_ERR 类型的 DOMException 异常。

  • name: 一个指定表示 worker 范围的 SharedWorkerGlobalScope 的标识名称的 DOMString,主要用于调试。

  • options: 创建实例时设定的包含了可选属性的对象。可用的属性包括:

    • type: 一个制定所创建 worker 类型的 DOMString。可设定的值为 classic 或者 module。 若不指定,默认值为 classic.

    • credentials: 一个指定要用于工作程序的凭据类型的 DOMString。可设定的值为 * omit*same-origin*include. * 若不指定,或者 type 设定为 classic, 默认值为 omit (无需凭据)。

    • *name: * 一个指定表示 worker 范围的 SharedWorkerGlobalScope 的标识名称的 DOMString,主要用于调试。

三、用法


主线程与 Shared Worker 的通信基于 MessagePort,允许双向消息传递。主线程通过 worker.port.postMessage()Worker 发送消息。Worker 接收到消息后,可以通过 port.postMessage() 回复。Shared Worker 中维护了多个连接的端口,每个连接可以互相广播消息,充当多页面通信的桥梁。

3.1 创建 Worker

编写一个 Shared Worker 文件(如 shared-worker.js):

// shared-worker.js
const connections = [];

// 处理新的连接
self.onconnect = event => {
const port = event.ports[0];
connections.push(port);

// 监听消息并广播到所有连接
port.onmessage = event => {
const message = event.data;
connections.forEach(conn => conn.postMessage(`Broadcast: ${message}`));
};
};

3.2 引入 Worker

创建 Shared Worker 并与其通信:

const worker = new SharedWorker('shared-worker.js');
worker.port.start();

// 接收广播消息
worker.port.onmessage = event => {
console.log('Received broadcast:', event.data);
};

// 向 Shared Worker 发送消息
worker.port.postMessage('Hello from this tab!');