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 相关文章推荐
最新优化收藏到网摘代码(digg,diigo)
Feb 07 Javascript
关于javascript DOM事件模型的两件事
Jul 22 Javascript
Javascript中valueOf与toString区别浅析
Mar 19 Javascript
js打开新窗口方法整理
Feb 17 Javascript
js实现同一个页面多个渐变效果的方法
Apr 10 Javascript
javascript实现继承的简单实例
Jul 26 Javascript
javascript中arguments,callee,caller详解
Mar 16 Javascript
判断数组是否包含某个元素的js函数实现方法
May 19 Javascript
使用MUI框架模拟手机端的下拉刷新和上拉加载功能
Sep 04 Javascript
浅谈Vue-cli单文件组件引入less,sass,css样式的不同方法
Mar 13 Javascript
利用原生的JavaScript实现简单拼图游戏
Nov 18 Javascript
jquery+css实现Tab栏切换的代码实例
May 14 jQuery
详解如何使用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初学者最感迷茫的问题小结
2010/03/27 PHP
cakephp2.X多表联合查询join及使用分页查询的方法
2017/02/23 PHP
使用jscript实现二进制读写脚本代码
2008/06/09 Javascript
javascript 处理HTML元素必须避免使用的一种方法
2009/07/30 Javascript
同一个表单 根据要求递交到不同页面的实现方法小结
2009/08/05 Javascript
在JavaScript中获取请求的URL参数[正则]
2010/12/25 Javascript
js获取当前月的第一天和最后一天的小例子
2013/11/18 Javascript
js确认删除对话框适用于a标签及submit
2014/07/10 Javascript
JavaScript中判断整字类型最简洁的实现方法
2014/11/08 Javascript
js表格排序实例分析(支持int,float,date,string四种数据类型)
2015/05/06 Javascript
实例讲解jQuery中对事件的命名空间的运用
2016/05/24 Javascript
js 函数式编程学习笔记
2017/03/25 Javascript
vue 实现类似淘宝星级评分的示例
2018/03/01 Javascript
Vue 微信端扫描二维码苹果端却只能保存图片问题(解决方法)
2020/01/19 Javascript
[42:11]TNC vs Pain 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
详解Python的Django框架中inclusion_tag的使用
2015/07/21 Python
Python列表切片用法示例
2017/04/19 Python
详谈python http长连接客户端
2017/06/12 Python
django将图片上传数据库后在前端显式的方法
2018/05/25 Python
Django 连接sql server数据库的方法
2018/06/30 Python
详解Python字符串切片
2019/05/20 Python
Spark处理数据排序问题如何避免OOM
2020/05/21 Python
python使用多线程+socket实现端口扫描
2020/05/28 Python
HTML5 Notification(桌面提醒)功能使用实例
2014/03/17 HTML / CSS
世界上最大的二手相机店:KEN
2017/05/17 全球购物
英国网络托管和域名领导者:Web Hosting UK
2017/10/15 全球购物
Saucony澳大利亚官网:美国跑鞋品牌,运动鞋中的劳斯莱斯
2018/05/05 全球购物
印度电子产品购物网站:Vijay Sales
2021/02/16 全球购物
大学学习生活感言
2014/01/18 职场文书
党员承诺践诺书
2014/05/20 职场文书
体育运动口号
2014/06/09 职场文书
工作作风承诺书
2014/08/30 职场文书
颐和园的导游词
2015/01/30 职场文书
会议通知格式范文
2015/04/15 职场文书
同事去世追悼词
2015/06/23 职场文书
SpringCloud Alibaba 基本开发框架搭建过程
2021/06/13 Java/Android