经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » HTML/CSS » HTML5 » 查看文章
html5中sharedWorker实现多页面通信的示例代码
来源:jb51  时间:2021/5/10 8:46:24  对本文有异议

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

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

  1. // 登录的页面
  2. localStorage.setItem('login', true);
  3.  
  4. // 其他页面
  5. document.addEventListener("visibilitychange", function() {
  6. if (localStorage.setItem('login') === 'true') {
  7. alert('你已登录,请刷新页面');
  8. }
  9. }

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

什么是sharedWorker

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

  1. 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,代码如下:

  1. // page.js
  2. let myWorker = new SharedWorker('worker.js');
  3. // page通过worker port发送消息
  4. myWorker.port.postMessage('哼哼');
  5. // page通过worker port接收消息
  6. myWorker.port.onmessage = (e) => console.log(e.data);
  7.  
  8. // worker.js
  9. onconnect= function(e) {
  10. const port = e.ports[0];
  11. port.postMessage('哈嘿');
  12. port.onmessage = (e) => {
  13. console.log(e.data);
  14. }
  15. }

调试sharedWorker

在上面的例子中,我们在worker中使用了console.log来打印来自页面的message,那么到哪里可以看到打印的log呢?我们可以在浏览器地址栏里面输入 `chrome://inspect,然后在侧边栏选中shared workers了,就可以看到浏览器,目前在运行的所有worker。点击inspect会打开一个开发者工具,然后就可以看到输出的log了。

这里我们看到我们的worker名字是untitled,那是因为sharedworker 构造函数还支持传入第二个参数作为名字:

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

多页面发布消息

回到文章一开始的例子,我们前面实现了页面和worker之间的通信,那么该如何让worker向多个页面发送消息呢?一个思路就是我们把port缓存起来,作为一个port pool,这样当我们需要向所有页面广播消息的时候,就可以遍历port,然后发送消息:

  1. // worker js
  2. const portPool = [];
  3. onconnect= function(e) {
  4. const port = e.ports[0];
  5. // 在connect时将 port添加到 portPool中
  6. portPool.push(port);
  7. port.postMessage('哈嘿');
  8. port.onmessage = (e) => {
  9. console.log(e.data);
  10. }
  11. }
  12.  
  13. function boardcast(message) {
  14. portPool.forEach(port => {
  15. port.portMessage(port);
  16. })
  17. }

这样我们就基本实现了向多个页面广播消息的功能。

清除无效的port

上面的实现中有一个问题,就是在页面关闭后,workerPool中的port并不会自动清除,造成内存的白白浪费。我们可以在页面关闭前通知shared worker页面将要关闭,然后让worker将无效的 messagePort 从 portPool 中移除。

  1. // 页面
  2. window.onbeforeunload = () => {
  3. myWorker.port.postMessage('TO BE CLOSED');
  4. };
  5.  
  6. // worker.js
  7. const portPool = [];
  8. onconnect = function(e) {
  9. var port = e.ports[0];
  10. portPool.push(port);
  11. port.onmessage = function(e) {
  12. console.log(e);
  13. if (e.data === 'TO BE CLOSED') {
  14. const index = ports.findIndex(p => p === port);
  15. portPool.splice(index, 1);
  16. }
  17. var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
  18. port.postMessage(workerResult);
  19. }
  20. }
  21.  
  22. function boardcast(message) {
  23. portPool.forEach(port => {
  24. port.portMessage(port);
  25. })
  26. }

这样,我们就实现了一个简单的多页面广播的sharedWorker。我们可以用它来广播一下时间:

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

参考

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

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号