JavaScript中sharedWorker 实现多页面通信的实例详解

 更新时间:2021年04月26日 14:47:01   作者:饭特稠  
这篇文章主要介绍了JavaScript中sharedWorker 实现多页面通信,通过给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

是这样的,今天玩github,先是在没有登录浏览了一些页面,然后在某一页面进行了登录。这时再切换的其他页面时就看到了下面的提示:

那么这是怎么做到的呢?我们可以想到,一种办法是 localStorage,在某一个页面登录时,修改localStorage 状态,其他页面在显示的时候,读取最新的状态,然后显示提示:

// 登录的页面
localStorage.setItem('login', true);

// 其他页面
document.addEventListener("visibilitychange", function() {
	if (localStorage.setItem('login') === 'true') {
		alert('你已登录,请刷新页面');
	}
}

然而,github并没有这么做,localStorage里也找不到相关的字段,一番查找之后,发现他们是用 sharedWorker 实现的。那我们就来了解下sharedworker

什么是sharedWorker

sharedWorker 顾名思义,是 worker 的一种,可以由所有同源的页面共享。同Worker的api一样,传入js的url,就可以注册一个 sharedWorker 实例:

let myWorker = new SharedWorker('worker.js');

但是与普通 Worker 不同的是:
1 同一个js url 只会创建一个 sharedWorker,其他页面再使用同样的url创建sharedWorker,会复用已创建的 worker,这个worker由那几个页面共享。
2 sharedWorker通过port来发送和接收消息

接下来,我们看一下具体是 worker 和页面之间是如何发送和接收消息的。

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了。

这里我们看到我们的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。我们可以用它来广播一下时间:

setInterval(() => boardcast(Date.now()), 1000);

参考

https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker/SharedWorker
https://github.com/mdn/simple-shared-worker

到此这篇关于JavaScript中sharedWorker 实现多页面通信的文章就介绍到这了,更多相关js sharedWorker多页面通信内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Next.js路由组使用之组织路由结构示例详解

    Next.js路由组使用之组织路由结构示例详解

    这篇文章主要为大家介绍了Next.js路由组使用之组织路由结构示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • js实现图片无缝滚动特效

    js实现图片无缝滚动特效

    这篇文章主要为大家详细介绍了js实现图片无缝循环滚动特效的相关资料,本实例在网页中较为常见,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-01-01
  • 支付宝小程序实现类似微信多行输入功能(思路详解)

    支付宝小程序实现类似微信多行输入功能(思路详解)

    这篇文章主要介绍了支付宝小程序实现类似微信多行输入功能,输入超过 8 行的时候会出现滚动,这样做的好处就是输入框不会直接顶到页面最顶部,支付宝小程序实现多行输入框:使用textarea多行输入框实现,感兴趣的朋友一起看看吧
    2024-02-02
  • 你可能不知道的JavaScript位运算符详解

    你可能不知道的JavaScript位运算符详解

    位运算符是在数字底层(即表示数字的32个数位)进行操作的,下面这篇文章主要给大家介绍了一些你可能不知道的JavaScript位运算符的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • BootstrapValidator实现表单验证功能

    BootstrapValidator实现表单验证功能

    这篇文章主要为大家详细介绍了BootstrapValidator实现表单验证功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-11-11
  • JS实现加载和读取XML文件的方法详解

    JS实现加载和读取XML文件的方法详解

    这篇文章主要介绍了JS实现加载和读取XML文件的方法,结合实例形式分析了javascript针对xml文件的加载与读取相关实现步骤与操作技巧,需要的朋友可以参考下
    2017-04-04
  • layui中layer前端组件实现图片显示功能的方法分析

    layui中layer前端组件实现图片显示功能的方法分析

    这篇文章主要介绍了layui中layer前端组件实现图片显示功能的方法,结合实例形式分析了layui中layer组件调用图片显示功能的操作方法与相关注意事项,并提供了layer与layui源码下载,需要的朋友可以参考下
    2017-10-10
  • 20170918 前端开发周报之JS前端开发必看

    20170918 前端开发周报之JS前端开发必看

    本文给大家分享了最新版js 前端开发周报,内容非常不错,具有参考借鉴价值,需要的朋友参考下吧
    2017-09-09
  • iScroll中事件点击触发两次解决方案

    iScroll中事件点击触发两次解决方案

    iScroll是我们在做手机网页中常用的滑动控件之一。单说其功能已相当丰富。但个别时候也是会掉坑的,正好这次就遇上了。在android的app中嵌入网页时不少手机会出现一次点击两次触发的现象。经过一段时间的折腾,总算想到了一个还算合理的解决放案。
    2015-03-03
  • layer弹出层 iframe层去掉滚动条的实例代码

    layer弹出层 iframe层去掉滚动条的实例代码

    今天小编就为大家分享一篇layer弹出层 iframe层去掉滚动条的实例代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08

最新评论