html5中sharedWorker实现多页面通信的示例代码


Posted in Javascript onMay 07, 2021

是这样的,今天玩github,先是在没有登录浏览了一些页面,然后在某一页面进行了登录。这时再切换的其他页面时就看到了下面的提示:

html5中sharedWorker实现多页面通信的示例代码

那么这是怎么做到的呢?我们可以想到,一种办法是 localStorage,在某一个页面登录时,修改localStorage 状态,其他页面在显示的时候,读取最新的状态,然后显示提示:

// 登录的页面
localStorage.setItem('login', true);
 
// 其他页面
document.addEventListener("visibilitychange", function() {
    if (localStorage.setItem('login') === 'true') {
        alert('你已登录,请刷新页面');
    }
}

html5中sharedWorker实现多页面通信的示例代码

然而,github并没有这么做,localStorage里也找不到相关的字段,一番查找之后,发现他们是用 sharedWorker 实现的。那我们就来了解下sharedworker

什么是sharedWorker

sharedWorker 顾名思义,是 worker 的一种,可以由所有同源的页面共享。同Worker的api一样,传入js的url,就可以注册一个 sharedWorker 实例:

let myWorker = new SharedWorker('worker.js');

接下来,我们看一下具体是 worker 和页面之间是如何发送和接收消息的。但是与普通 Worker 不同的是:
1 同一个js url 只会创建一个 sharedWorker,其他页面再使用同样的url创建sharedWorker,会复用已创建的 worker,这个worker由那几个页面共享。
2 sharedWorker通过port来发送和接收消息

messagePort

假设我们有两个js,一个是跑在页面里的 page.js,另一个是跑在 worker里的 worker.js。那么我们要在 page.js 里注册一个 sharedWorker,代码如下:

// page.js
let myWorker = new SharedWorker('worker.js');
// page通过worker port发送消息
myWorker.port.postMessage('哼哼');
// page通过worker port接收消息
myWorker.port.onmessage = (e) => console.log(e.data);
 
// worker.js
onconnect= function(e) {
    const port = e.ports[0];
    port.postMessage('哈嘿');
    port.onmessage = (e) => {
        console.log(e.data);
    }
}

调试sharedWorker

在上面的例子中,我们在worker中使用了console.log来打印来自页面的message,那么到哪里可以看到打印的log呢?我们可以在浏览器地址栏里面输入 `chrome://inspect,然后在侧边栏选中shared workers了,就可以看到浏览器,目前在运行的所有worker。点击inspect会打开一个开发者工具,然后就可以看到输出的log了。

html5中sharedWorker实现多页面通信的示例代码

这里我们看到我们的worker名字是untitled,那是因为sharedworker 构造函数还支持传入第二个参数作为名字:

let myWorker = new SharedWorker('worker.js', 'awesome worker');

回到文章一开始的例子,我们前面实现了页面和worker之间的通信,那么该如何让worker向多个页面发送消息呢?一个思路就是我们把port缓存起来,作为一个port pool,这样当我们需要向所有页面广播消息的时候,就可以遍历port,然后发送消息:多页面发布消息

// worker js
const portPool = [];
onconnect= function(e) {
    const port = e.ports[0];
    // 在connect时将 port添加到 portPool中
    portPool.push(port);
    port.postMessage('哈嘿');
    port.onmessage = (e) => {
        console.log(e.data);
    }
}
 
function boardcast(message) {
    portPool.forEach(port => {
        port.portMessage(port);
    })
}

这样我们就基本实现了向多个页面广播消息的功能。

清除无效的port

上面的实现中有一个问题,就是在页面关闭后,workerPool中的port并不会自动清除,造成内存的白白浪费。我们可以在页面关闭前通知shared worker页面将要关闭,然后让worker将无效的 messagePort 从 portPool 中移除。

// 页面
window.onbeforeunload = () => {
  myWorker.port.postMessage('TO BE CLOSED');
};
 
// worker.js
const portPool = [];
onconnect = function(e) {
  var port = e.ports[0];
  portPool.push(port);
  port.onmessage = function(e) {
    console.log(e);
    if (e.data === 'TO BE CLOSED') {
      const index = ports.findIndex(p => p === port);
      portPool.splice(index, 1);
    }
    var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
    port.postMessage(workerResult);
  }
}
 
function boardcast(message) {
    portPool.forEach(port => {
        port.portMessage(port);
    })
}

这样,我们就实现了一个简单的多页面广播的sharedWorker。我们可以用它来广播一下时间:

参考

https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker/SharedWorker
https://github.com/mdn/simple-shared-worker

到此这篇关于html5中sharedWorker实现多页面通信的示例代码的文章就介绍到这了

Javascript 相关文章推荐
js 调整select 位置的函数
Feb 21 Javascript
一个简单的弹性返回顶部JS代码实现介绍
Jun 09 Javascript
JavaScript中的正则表达式简明总结
Apr 04 Javascript
js去除输入框中所有的空格和禁止输入空格的方法
Jun 09 Javascript
jquery实现邮箱自动填充提示功能
Nov 17 Javascript
JavaScript 身份证号有效验证详解及实例代码
Oct 20 Javascript
最全正则表达式总结:验证QQ号、手机号、Email、中文、邮编、身份证、IP地址等
Aug 16 Javascript
Vue的路由动态重定向和导航守卫实例
Mar 17 Javascript
基于vue-simplemde实现图片拖拽、粘贴功能
Apr 12 Javascript
微信小程序HTTP接口请求封装代码实例
Sep 05 Javascript
微信小程序 轮播图实现原理及优化详解
Sep 29 Javascript
浅析vue中的provide / inject 有什么用处
Nov 10 Javascript
详解如何使用Node.js实现热重载页面
May 06 #Javascript
关于Vue Router的10条高级技巧总结
May 06 #Vue.js
在JavaScript中如何使用宏详解
May 06 #Javascript
如何用JS实现简单的数据监听
May 06 #Javascript
详解TS数字分隔符和更严格的类属性检查
May 06 #Javascript
JS中一些高效的魔法运算符总结
May 06 #Javascript
react国际化react-intl的使用
You might like
PHP nl2br函数 将换行字符转成 <br>
2009/08/21 PHP
PHP下通过file_get_contents的代理使用方法
2011/02/16 PHP
thinkPHP5.0框架应用请求生命周期分析
2017/03/25 PHP
PHP检查文件是否存在,不存在自动创建及读取文件内容操作示例
2020/01/23 PHP
js浮动图片的动态效果
2013/07/10 Javascript
JS实现遮罩层效果的简单实例
2013/11/12 Javascript
js设置function参数默认值(适合没有传参情况)
2014/02/24 Javascript
JS、CSS以及img对DOMContentLoaded事件的影响
2014/08/12 Javascript
JavaScript中的bold()方法使用详解
2015/06/08 Javascript
js实现的Easy Tabs选项卡用法实例
2015/09/06 Javascript
JavaScript基础篇(3)之Object、Function等引用类型
2015/11/30 Javascript
JS中的hasOwnProperty()、propertyIsEnumerable()和isPrototypeOf()
2016/08/11 Javascript
Jquery根据浏览器窗口改变调整大小的方法
2017/02/07 Javascript
JavaScript正则表达式简单实用实例
2017/06/23 Javascript
Vue.js学习记录之在元素与template中使用v-if指令实例
2017/06/27 Javascript
JS闭包的几种常见形式实例详解
2017/09/16 Javascript
vue使用监听实现全选反选功能
2018/07/06 Javascript
解决vue.js this.$router.push无效的问题
2018/09/03 Javascript
vue v-for循环重复数据无法添加问题解决方法【加track-by='索引'】
2019/03/15 Javascript
JavaScript自动生成 年月范围 选择功能完整示例【基于jQuery插件】
2019/09/03 jQuery
[01:07:20]DOTA2-DPC中国联赛 正赛 Dynasty vs XG BO3 第二场 2月2日
2021/03/11 DOTA
python搜索指定目录的方法
2015/04/29 Python
python pandas库的安装和创建
2019/01/10 Python
python Pandas库基础分析之时间序列的处理详解
2019/07/13 Python
python数据类型强制转换实例详解
2020/06/22 Python
Django celery异步任务实现代码示例
2020/11/26 Python
python 通过pip freeze、dowload打离线包及自动安装的过程详解(适用于保密的离线环境
2020/12/14 Python
Agoda香港:全球特价酒店预订
2017/05/07 全球购物
俄罗斯在线水暖商店:Perfecto.ru
2019/10/25 全球购物
社团文化节策划书
2014/02/01 职场文书
2014信息公开实施方案
2014/02/22 职场文书
装修设计师求职信
2014/02/26 职场文书
根叔历年演讲稿
2014/05/20 职场文书
趣味运动会标语口号
2015/12/26 职场文书
2019年冬至:天冷暖人心的问候祝福语大全
2019/12/20 职场文书
python+pytest接口自动化之token关联登录的实现
2022/04/06 Python