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 相关文章推荐
html5的自定义data-*属性和jquery的data()方法的使用示例
Aug 21 Javascript
Javascript 运动中Offset的bug解决方案
Dec 24 Javascript
js仿微博实现统计字符和本地存储功能
Dec 22 Javascript
jquery实现页面常用的返回顶部效果
Mar 04 Javascript
js实现的xml对象转json功能示例
Dec 24 Javascript
微信小程序 获取session_key和openid的实例
Aug 17 Javascript
基于vue开发的在线付费课程应用过程
Jan 25 Javascript
Node.js 使用request模块下载文件的实例
Sep 05 Javascript
JavaScript类型相关的常用操作总结
Feb 14 Javascript
jQuery使用ajax传递json对象到服务端及contentType的用法示例
Mar 12 jQuery
JS+CSS实现炫酷光感效果
Sep 05 Javascript
vue实现两个区域滚动条同步滚动
Dec 13 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的中问验证码
2006/11/25 PHP
ThinkPHP调用common/common.php函数提示错误function undefined的解决方法
2014/08/25 PHP
PHP单例模式详解及实例代码
2016/12/21 PHP
jquery imgareaselect 使用利用js与程序结合实现图片剪切
2009/07/30 Javascript
在JavaScript中获取请求的URL参数[正则]
2010/12/25 Javascript
使用隐藏的new来创建对象
2011/03/29 Javascript
在浏览器中获取当前执行的脚本文件名的代码
2011/07/19 Javascript
js调用后台servlet方法实例
2013/06/09 Javascript
node.js中的fs.utimes方法使用说明
2014/12/15 Javascript
MVVM模式中ViewModel和View、Model有什么区别?
2015/06/19 Javascript
jquery对象和DOM对象的任意相互转换
2016/02/21 Javascript
jQuery插件HighCharts绘制2D柱状图、折线图的组合双轴图效果示例【附demo源码下载】
2017/03/09 Javascript
JavaScript装饰器函数(Decorator)实例详解
2017/03/30 Javascript
基于Vue的文字跑马灯组件(npm 组件包)
2017/05/24 Javascript
D3.js进阶系列之CSV表格文件的读取详解
2017/06/06 Javascript
JavaScript 性能提升之路(推荐)
2019/04/10 Javascript
vue 的 solt 子组件过滤过程解析
2019/09/07 Javascript
[02:47]DOTA2英雄基础教程 野性怒吼兽王
2013/12/05 DOTA
[03:37]2014DOTA2国际邀请赛 主赛事第一日胜者组TOPPLAY
2014/07/19 DOTA
Python的Bottle框架的一些使用技巧介绍
2015/04/08 Python
详细解读tornado协程(coroutine)原理
2018/01/15 Python
ubuntu安装mysql pycharm sublime
2018/02/20 Python
用python拟合等角螺线的实现示例
2019/12/27 Python
一些关于python 装饰器的个人理解
2020/08/31 Python
python中scipy.stats产生随机数实例讲解
2021/02/19 Python
介绍一下grep命令的使用
2015/06/12 面试题
英语国培研修感言
2014/02/13 职场文书
租房协议书怎么写
2014/04/10 职场文书
《金色的脚印》教后反思
2014/04/23 职场文书
银行金融服务方案
2014/06/11 职场文书
2015年幼儿园新年寄语
2014/12/08 职场文书
2016教师校本培训心得体会
2016/01/08 职场文书
一封真诚的自荐信帮你赢得机会
2019/05/07 职场文书
如何书写你的职业生涯规划书?
2019/06/27 职场文书
Django项目如何获得SSL证书与配置HTTPS
2021/04/30 Python
古见同学有交流障碍症 第二季宣传CM公开播出
2022/04/11 日漫