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 相关文章推荐
许愿墙中用到的函数
Oct 07 Javascript
Javascript 读书笔记索引贴
Jan 11 Javascript
qTip2 精致的基于jQuery提示信息插件
Feb 17 Javascript
Javascript中call的两种用法实例
Dec 13 Javascript
js之ActiveX控件使用说明 new ActiveXObject()
Mar 03 Javascript
javascript实现瀑布流自适应遇到的问题及解决方案
Jan 28 Javascript
微信QQ的二维码登录原理js代码解析
Jun 23 Javascript
JavaScript之Map和Set_动力节点Java学院整理
Jun 29 Javascript
JavaScript实现求最大公共子串的方法
Feb 03 Javascript
vue多层嵌套路由实例分析
Mar 19 Javascript
taro 实现购物车逻辑的实例代码
Jun 05 Javascript
JavaScript实现切换多张图片
Jan 27 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
ZF等常用php框架中存在的问题
2008/01/10 PHP
有道搜索和IP138的IP的API接口(PHP应用)
2012/11/29 PHP
深入php常用函数的使用汇总
2013/06/08 PHP
PHP小教程之实现链表
2014/06/09 PHP
浅谈PHP拦截器之__set()与__get()的理解与使用方法
2016/10/18 PHP
php中pcntl_fork创建子进程的方法实例
2019/03/14 PHP
JQUERY对单选框(radio)操作的小例子
2013/04/25 Javascript
javascript打印输出json实例
2013/11/11 Javascript
在百度知道团队中快速审批新成员的js脚本
2014/02/02 Javascript
jquery判断密码强度的验证代码
2020/04/22 Javascript
Angularjs在初始化未完毕时出现闪烁问题的解决方法分析
2016/08/05 Javascript
BootStrap下拉菜单和滚动监听插件实现代码
2016/09/26 Javascript
利用vueJs实现图片轮播实例代码
2017/06/03 Javascript
JS实现商品筛选功能
2020/08/19 Javascript
通俗解释JavaScript正则表达式快速记忆
2017/08/23 Javascript
JS中利用swiper实现3d翻转幻灯片实例代码
2017/08/25 Javascript
vue初尝试--项目结构(推荐)
2018/01/30 Javascript
vue-cli构建项目下使用微信分享功能
2018/05/28 Javascript
Vue瀑布流插件的使用示例
2018/09/19 Javascript
vue 框架下自定义滚动条(easyscroll)实现方法
2019/08/29 Javascript
Python 十六进制整数与ASCii编码字符串相互转换方法
2018/07/09 Python
Python中出现IndentationError:unindent does not match any outer indentation level错误的解决方法
2020/04/18 Python
python3实现猜数字游戏
2020/12/07 Python
opencv中图像叠加/图像融合/按位操作的实现
2020/04/01 Python
Java爬虫技术框架之Heritrix框架详解
2020/07/22 Python
香港永安旅游网:Wing On Travel
2017/04/10 全球购物
英国女士家居服网站:hush
2017/08/09 全球购物
汉森批发:Hansen Wholesale
2018/05/24 全球购物
小学教研工作制度
2014/01/15 职场文书
电子信息科学专业自荐信
2014/01/30 职场文书
小学一年级学生评语
2014/04/22 职场文书
乡镇八一建军节活动方案
2014/08/24 职场文书
支部书记四风问题自我剖析材料
2014/09/29 职场文书
2015年人力资源工作总结
2015/04/08 职场文书
民间借贷被告代理词
2015/05/23 职场文书
PostgreSQL将数据加载到buffer cache中操作方法
2021/04/16 PostgreSQL