浏览器中的跨页面通信(二):SharedWorker

2023-10-07  本文已影响0人  涅槃快乐是金

介绍

SharedWorker 接口代表一种特定类型的 worker,可以从几个浏览上下文中访问,例如几个窗口、iframe 或其他 worker。它们实现一个不同于普通 worker 的接口,具有不同的全局作用域SharedWorkerGlobalScope

备注: 如果要使 SharedWorker 连接到多个不同的页面,这些页面必须是同源的(相同的协议、host 以及端口)。

又称共享线程。之所以可以在多个浏览器页签中共享信息,是因为在页签的html中创建SharedWorker时,如果第一个参数相同,则视为同一线程,所以只要保证创建时的第一个参数相同,就可以在多页签间共享信息。

方法介绍

var myWorker = new SharedWorker("worker.js");
first.onchange = function () {
  myWorker.port.postMessage([first.value, second.value]);
  console.log("Message posted to worker");
};

second.onchange = function () {
  myWorker.port.postMessage([first.value, second.value]);
  console.log("Message posted to worker");
};

myWorker.port.onmessage = function (e) {
  result1.textContent = e.data;
  console.log("Message received from worker");
};

可以看到Woker类的API是相当简洁的,只有两个最常用的方法,一个事件,下面我们来通过实际的例子看看。

示例

调试:

地址栏chrome://inspect,点击shared workers,点击inspect

构建worker脚本

let pool = [];
onconnect = function (e) {
  let port = e.ports[0];
  pool.push(port);
  port.onmessage = function (e) {
    pool.forEach((v) => {
      v != port && v.postMessage(e.data);
    });
  };
};

构建数据共享通道

export class SharedDataChannel {
  constructor(url, cb) {
    this.sharedWorker = new SharedWorker(url);
    this.sharedWorker.port.onmessage = (e) => {
      cb && cb(e.data);
    };
  }

  post(data) {
    this.sharedWorker.port.postMessage(data);
  }
}

在多个页面进行初始化

<script type="module">
    import { SharedDataChannel } from "./index.js";
    const channel = new SharedDataChannel("./worker.js", (res) => {
    document.querySelector("#content").innerHTML += `${res} </br>`;
    });
    document.querySelector("#send").addEventListener("click", () => {
    channel.post("登录页面发送的数据");
    });
</script>

<body>
    登录页面

    <button id="send">发送</button>
    <p id="content"></p>
</body>

调试

chrome://inspect/#workers 导航到 chrome://inspect/#workers 并找到共享的 worker,然后单击"inspect",然后你可以拉起 SharedWorker 的控制台。

效果

页面关闭清除Shared Worker
.在页面关闭后,workerPool中的port并不会自动清除,造成内存的占用
.通过监听页面关闭,通知worker关闭
.通过框架的生命周期
.通过浏览器自带的生命周期window.onbeforeunload

// 关闭页面的时候,关闭 SharedWorker
window.addEventListener('beforeunload', () => {
    sharedWorker.port.postMessage({
        type: 'close',
        uuid: uuid
    });
});

// SharedWorker.js
/** 省略其他代码 **/
onconnect = (e) => {
    const port = e.ports[0];

    port.onmessage = (e) => {
        if (e.data.type === 'close') {
            const index = ports.indexOf(port);
            ports.splice(index, 1);
            return;
        }
    };
};

兼容性

上一篇下一篇

猜你喜欢

热点阅读