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 相关文章推荐
jquery中focus()函数实现当对象获得焦点后自动把光标移到内容最后
Sep 29 Javascript
jQuery实现视频作为全屏幕背景
Dec 18 Javascript
基于jquery实现放大镜效果
Aug 17 Javascript
jQuery Tags Input Plugin(添加/删除标签插件)详解
Jun 20 Javascript
js复制内容到剪贴板代码,js复制代码的简单实例
Oct 27 Javascript
Bootstrap 模态框(Modal)插件代码解析
Dec 21 Javascript
javascript九宫格图片随机打乱位置的实现方法
Mar 15 Javascript
vue实现打印功能的两种方法
Sep 07 Javascript
vue移动端项目缓存问题实践记录
Oct 29 Javascript
Windows上node.js的多版本管理工具用法实例分析
Nov 06 Javascript
js实现整体缩放页面适配移动端
Mar 31 Javascript
vue打包通过image-webpack-loader插件对图片压缩优化操作
Nov 12 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
全国FM电台频率大全 - 18 湖南省
2020/03/11 无线电
使用PHP和XSL stylesheets转换XML文档
2006/10/09 PHP
PHP中数组的分组排序实例
2014/06/01 PHP
ThinkPHP模板输出display用法分析
2014/11/26 PHP
Windows下编译PHP5.4和xdebug全记录
2015/04/03 PHP
使用XHProf查找PHP性能瓶颈的实例
2017/12/13 PHP
JavaScript入门之事件、cookie、定时等
2011/10/21 Javascript
Javascript类定义语法,私有成员、受保护成员、静态成员等介绍
2011/12/08 Javascript
JS实现遮罩层效果的简单实例
2013/11/12 Javascript
做好七件事帮你提升jQuery的性能
2014/02/06 Javascript
jQuery中的val()示例应用
2014/02/26 Javascript
Jquery插件编写简明教程
2014/03/25 Javascript
jQuery响应enter键的实现思路
2014/04/18 Javascript
22点关于jquery性能优化的建议
2014/05/28 Javascript
详解js闭包
2014/09/02 Javascript
js实现绿白相间竖向网页百叶窗动画切换效果
2015/03/02 Javascript
情人节单身的我是如何在敲完代码之后收到12束玫瑰的(javascript)
2015/08/21 Javascript
js+css实现文字散开重组动画特效代码分享
2015/08/21 Javascript
使用canvas实现仿新浪微博头像截取上传功能
2015/09/02 Javascript
浅谈js的url解析函数封装
2016/06/28 Javascript
微信小程序 JS动态修改样式的实现代码
2017/02/10 Javascript
IntelliJ IDEA 安装vue开发插件的方法
2017/11/21 Javascript
js中url对象化管理分析
2017/12/29 Javascript
详解vue2.0监听属性的使用心得及搭配计算属性的使用
2018/07/18 Javascript
vue+element-ui动态生成多级表头的方法
2018/08/28 Javascript
JS面向对象实现飞机大战
2020/08/26 Javascript
Javascript实现贪吃蛇小游戏(含详细注释)
2020/10/23 Javascript
使用Python神器对付12306变态验证码
2016/01/05 Python
python或C++读取指定文件夹下的所有图片
2019/08/31 Python
python实现银行账户系统
2021/02/22 Python
CSS3制作翻转效果_动力节点Java学院整理
2017/07/11 HTML / CSS
淘宝活动策划方案
2014/02/06 职场文书
招商引资工作汇报
2014/10/28 职场文书
护士长2014年度工作总结
2014/11/11 职场文书
学习党史心得体会2016
2016/01/23 职场文书
《绝招》教学反思
2016/02/20 职场文书