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 相关文章推荐
客户端限制只能上传jpg格式图片的js代码
Dec 09 Javascript
超链接的禁用属性Disabled使用示例
Jul 31 Javascript
jquery实现在页面加载的时自动为日期插件添加当前日期
Aug 20 Javascript
判断访客终端类型集锦
Jun 05 Javascript
JavaScript代码生成PDF文件的方法
Feb 26 Javascript
jquery实现图片列表鼠标移入微动
Dec 01 Javascript
JS表单数据验证的正则表达式(常用)
Feb 18 Javascript
详解JavaScript 中getElementsByName在IE中的注意事项
Feb 21 Javascript
详解vue-cli开发环境跨域问题解决方案
Jun 06 Javascript
jQuery实现所有验证通过方可提交的表单验证
Nov 21 jQuery
layer弹出框确定前验证:弹出消息框的方法(弹出两个layer)
Sep 21 Javascript
Vue+abp微信扫码登录的实现代码示例
Jan 06 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
杏林同学录(二)
2006/10/09 PHP
php array_walk() 数组函数
2011/07/12 PHP
什么情况下可以不写PHP的闭合标签“?>”
2014/08/28 PHP
extJs 文本框后面加上说明文字+下拉列表选中值后触发事件
2009/11/27 Javascript
JQuery扩展插件Validate—6 radio、checkbox、select的验证
2011/09/05 Javascript
js中的this关键字详解
2013/09/25 Javascript
JavaScript数组常用操作技巧汇总
2014/11/17 Javascript
javascript实现动态导入js与css等静态资源文件的方法
2015/07/25 Javascript
全面解析Bootstrap表单样式的使用
2016/09/09 Javascript
详解nodejs通过代理(proxy)发送http请求(request)
2017/09/22 NodeJs
VUE Error: getaddrinfo ENOTFOUND localhost
2018/05/03 Javascript
在移动端使用vue-router和keep-alive的方法示例
2018/12/02 Javascript
vue中监听返回键问题
2019/08/28 Javascript
JS实现网页端猜数字小游戏
2020/03/06 Javascript
Python 元组(Tuple)操作详解
2014/03/11 Python
python获取文件后缀名及批量更新目录下文件后缀名的方法
2014/11/11 Python
Python 实现 贪吃蛇大作战 代码分享
2016/09/07 Python
python去除拼音声调字母,替换为字母的方法
2018/11/28 Python
快速解决docker-py api版本不兼容的问题
2019/08/30 Python
Python中sorted()排序与字母大小写的问题
2020/01/14 Python
mac在matplotlib中显示中文的操作方法
2020/03/06 Python
Django模型中字段属性choice使用说明
2020/03/30 Python
CSS3 实现侧边栏展开收起动画
2014/12/22 HTML / CSS
新秀丽拉杆箱美国官方网站:Samsonite美国
2016/07/25 全球购物
美国宠物用品网站:Value Pet Supplies
2018/03/17 全球购物
阿姆斯特丹杜莎夫人蜡像馆官方网站:Madame Tussauds Amsterdam
2019/03/12 全球购物
Java工程师面试集锦之Spring框架
2013/06/16 面试题
农业资源与环境专业自荐信范文
2013/12/30 职场文书
写给女生的道歉信
2014/01/14 职场文书
《灰椋鸟》教学反思
2014/04/27 职场文书
大二学习计划书范文
2014/04/27 职场文书
门面房租房协议书
2014/12/01 职场文书
师德师风学习材料
2014/12/19 职场文书
红灯733-1型14管5波段半导体收音机
2021/04/22 无线电
用Python编写简单的gRPC服务的详细过程
2021/07/04 Python
手把手教你导入Go语言第三方库
2021/08/04 Golang