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 相关文章推荐
bcastr2.0 通用的图片浏览器
Nov 22 Javascript
用jscript实现新建word文档
Jun 15 Javascript
在javascript中执行任意html代码的方法示例解读
Dec 25 Javascript
jQuery仿360导航页图标拖动排序效果代码分享
Aug 24 Javascript
javascript特殊日历控件分享
Mar 07 Javascript
浅谈jQuery效果函数
Sep 16 Javascript
微信小程序tabbar不显示解决办法
Jun 08 Javascript
全选复选框JavaScript编写小结(附代码)
Aug 16 Javascript
Node.js 使用AngularJS的方法示例
May 11 Javascript
vue项目webpack中Npm传递参数配置不同域名接口
Jun 15 Javascript
Vuejs中的watch实例详解(监听者)
Jan 05 Javascript
Vue仿百度搜索功能
Dec 28 Vue.js
详解如何使用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实现多服务器session共享之NFS共享的方法
2007/03/16 PHP
PHP运行出现Notice : Use of undefined constant 的完美解决方案分享
2012/03/05 PHP
PHP函数preg_match_all正则表达式的基本使用详细解析
2013/08/31 PHP
PHP中常用的输出函数总结
2014/09/22 PHP
浅谈PHP中静态方法和非静态方法的相互调用
2016/10/04 PHP
php通过PHPExcel导入Excel表格到MySQL数据库的简单实例
2016/10/29 PHP
js 蒙版进度条(结合图片)
2010/03/10 Javascript
Jquery中删除元素的实现代码
2011/12/29 Javascript
一样的table?不一样的table(可编辑状态table)
2012/09/19 Javascript
jQuery选择器中含有空格的使用示例及注意事项
2013/08/25 Javascript
Ext4.2的Ext.grid.plugin.RowExpander无法触发事件解决办法
2014/08/15 Javascript
让IE8浏览器支持function.bind()方法
2014/10/16 Javascript
JQuery组件基于Bootstrap的DropDownList(完整版)
2016/07/05 Javascript
原生JS实现风箱式demo,并封装了一个运动框架(实例代码)
2016/07/22 Javascript
详解ECharts使用心得总结
2016/12/06 Javascript
vue2导航根据路由传值,而改变导航内容的实例
2017/11/10 Javascript
Vue项目组件化工程开发实践方案
2018/01/09 Javascript
vue-cli 引入、配置axios的方法
2018/05/08 Javascript
如何在Vue中抽离接口配置文件
2019/10/31 Javascript
Echarts实现多条折线可拖拽效果
2019/12/19 Javascript
简单了解JS打开url的方法
2020/02/21 Javascript
Python中enumerate函数代码解析
2017/10/31 Python
python实现批量修改服务器密码的方法
2019/08/13 Python
用Python画一个LinkinPark的logo代码实例
2019/09/10 Python
导入tensorflow时报错:cannot import name 'abs'的解决
2019/10/10 Python
python 实现检验33品种数据是否是正态分布
2019/12/09 Python
PyCharm设置Ipython交互环境和宏快捷键进行数据分析图文详解
2020/04/23 Python
python中threading开启关闭线程操作
2020/05/02 Python
英国最好的温室之家:Greenhouses Direct
2019/07/13 全球购物
高分子材料与工程专业个人求职信
2013/12/15 职场文书
小学清明节活动方案
2014/03/08 职场文书
公务员政审单位鉴定材料
2014/05/16 职场文书
就业推荐表院系意见
2015/06/05 职场文书
运动会闭幕式主持词
2015/07/01 职场文书
如何使用分区处理MySQL的亿级数据优化
2021/06/18 MySQL
golang的文件创建及读写操作
2022/04/14 Golang