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 相关文章推荐
[原创]提供复制本站内容时出现,该文章转自脚本之家等字样的js代码
Mar 27 Javascript
Javascript查询DBpedia小应用实例学习
Mar 07 Javascript
js控制表单奇偶行样式的简单方法
Jul 31 Javascript
Javascript基础教程之if条件语句
Jan 18 Javascript
javascript文本框内输入文字倒计数的方法
Feb 24 Javascript
移动端JQ插件hammer使用详解
Jul 03 Javascript
原生JavaScript实现瀑布流布局
Jun 28 Javascript
CodeMirror js代码加亮使用总结
Mar 25 Javascript
微信小程序如何获取用户头像和昵称
Sep 23 Javascript
Vue.js实现大屏数字滚动翻转效果
Nov 29 Javascript
vue中的v-model原理,与组件自定义v-model详解
Aug 04 Javascript
Openlayers实现图形绘制
Sep 28 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
PHP explode()函数用法、切分字符串
2012/10/03 PHP
PHP版本升级到7.x后wordpress的一些修改及wordpress技巧
2015/12/25 PHP
php处理单文件、多文件上传代码分享
2016/08/24 PHP
PHP替换Word中变量并导出PDF图片的实现方法
2020/11/26 PHP
js GridView 实现自动计算操作代码
2009/03/25 Javascript
JavaScript异步编程:异步数据收集的具体方法
2013/08/19 Javascript
jquery分页对象使用示例
2014/04/01 Javascript
js实现字符串的16进制编码不加密
2014/04/25 Javascript
nodejs简单实现中英文翻译
2015/05/04 NodeJs
百度地图给map添加右键菜单(判断是否为marker)
2016/03/04 Javascript
利用javascript实现的三种图片放大镜效果实例(附源码)
2017/01/23 Javascript
Ionic3实现图片瀑布流布局
2017/08/09 Javascript
微信通过页面(H5)直接打开本地app的解决方法
2017/09/09 Javascript
React中常见的动画实现的几种方式
2018/01/10 Javascript
vue+element-ui+ajax实现一个表格的实例
2018/03/09 Javascript
vue组件实现弹出框点击显示隐藏效果
2020/10/26 Javascript
JS实现生成由字母与数字组合的随机字符串功能详解
2018/05/25 Javascript
js实现文件上传功能 后台使用MultipartFile
2018/09/08 Javascript
详解如何为你的angular app构建一个第三方库
2018/12/07 Javascript
vue实现整屏滚动切换
2020/06/29 Javascript
Python下载指定页面上图片的方法
2016/05/12 Python
Python基础教程之内置函数locals()和globals()用法分析
2018/03/16 Python
Python 实现域名解析为ip的方法
2019/02/14 Python
Python Pandas数据中对时间的操作
2019/07/30 Python
Python有参函数使用代码实例
2020/01/06 Python
Python如何在DataFrame增加数值
2020/02/14 Python
网友共享的几个面试题关于Java和Unix等方面的
2016/09/08 面试题
食堂员工工作职责
2013/12/18 职场文书
促销活动总结
2014/04/28 职场文书
法制宣传月活动总结
2014/04/29 职场文书
学雷锋活动总结报告
2014/06/26 职场文书
三问三解心得体会
2014/09/05 职场文书
2014应届本科生自我评价
2014/09/13 职场文书
公司食堂管理制度
2015/08/05 职场文书
小程序教您怎样你零成本推广获取数万用户的方法
2019/07/30 职场文书
教你使用一行Python代码玩遍童年的小游戏
2021/08/23 Python