html多页面之间如何通信,html5中sharedWorker实现多页面通信代码示例

本篇文章小编给大家分享一下html5中sharedWorker实现多页面通信代码示例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。

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

1d8ba00ce4b6f7b7cf39b77105c0595b.png

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

// 登录的页面

localStorage.setItem('login', true);

// 其他页面

document.addEventListener("visibilitychange", function() {

if (localStorage.setItem('login') === 'true') {

alert('你已登录,请刷新页面');

}

}

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

9047162a536ea4e585e3d8f39e994a40.png

什么是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了。

490b889d202f3437b52a3ee137d5bf6a.png

这里我们看到我们的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);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值