zoukankan      html  css  js  c++  java
  • 实现多个标签页之间通信的几种方法(sharedworker)

     
    效果图.gif

    prologue

    • 之前在网上看到一个面试题:如何实现浏览器中多个标签页之间的通信。我目前想到的方法有三种:使用websocket协议、通过localstorage、以及使用html5浏览器的新特性SharedWorker。
    • websocket这里先不介绍了,全双工(full-duplex)通信自然可以实现多个标签页之间的通信,相信网上通过websocket实现聊天室的教程也不少
    • 接下来会介绍另外两个方法:监听localstorage和使用SharedWorker

    localstorage

    • localstorage是浏览器多个标签共用的存储空间,所以可以用来实现多标签之间的通信(ps:session是会话级的存储空间,每个标签页都是单独的)。
    • 直接在window对象上添加监听即可:
    window.onstorage = (e) => {console.log(e)}
    // 或者这样
    window.addEventListener('storage', (e) => console.log(e))
    • onstorage以及storage事件,针对都是非当前页面对localStorage进行修改时才会触发,当前页面修改localStorage不会触发监听函数。然后就是在对原有的数据的值进行修改时才会触发,比如原本已经有一个key会a值为b的localStorage,你再执行:localStorage.setItem('a', 'b')代码,同样是不会触发监听函数的。

    webworker

    • 我们都知道JavaScript是单线程的,但是浏览器是拥有过个线程的比如:gui渲染线程、JS引擎线程、事件触发线程、异步http请求线程。
    • webworker作为浏览器的一个新特性,可以提供一个额外的线程来执行一些js代码,并且不会影响到浏览器用户界面。
    • 应用场景:比如页面中包含耗时较大的算法代码时,就会阻塞线程影响浏览器渲染等等。这时候就可把耗时代码,放到webworker(另一个线程)中执行。
    • 注意,这种多线程能力不是JavaScript语言原生具有的,而是浏览器宿主环境提供的。
    • 普通的webworker直接使用new Worker()即可创建,这种webworker是当前页面专有的。然后还有种共享worker(SharedWorker),这种是可以多个标签页、iframe共同使用的,接下来介绍如何使用SharedWorker实现标签页之间的通信。

    SharedWorker

    • SharedWorker可以被多个window共同使用,但必须保证这些标签页都是同源的(相同的协议,主机和端口号)
    • 首先新建一个js文件worker.js,具体代码如下:
    // sharedWorker所要用到的js文件,不必打包到项目中,直接放到服务器即可
    let data = ''
    onconnect = function (e) {
      let port = e.ports[0]
    
      port.onmessage = function (e) {
        if (e.data === 'get') {
          port.postMessage(data)
        } else {
          data = e.data
        }
      }
    }
    • webworker端(暂且这样称呼)的代码就如上,只需注册一个onmessage监听信息的事件,客户端(即使用sharedWorker的标签页)发送message时就会触发。

    • 注意webworker无法在本地使用,出于浏览器本身的安全机制,所以我这次的示例也是放在服务器上的,worker.jsindex.html在同一目录。

       
      image
    • 因为客户端和webworker端的通信不像websocket那样是全双工的,所以客户端发送数据和接收数据要分成两步来处理。示例中会有两个按钮,分别对应的向sharedWorker发送数据的请求以及获取数据的请求,但他们本质上都是相同的事件--发送消息。

    • webworker端会进行判断,传递的数据为'get'时,就把变量data的值回传给客户端,其他情况,则把客户端传递过来的数据存储到data变量中。下面是客户端的代码:

    // 这段代码是必须的,打开页面后注册SharedWorker,显示指定worker.port.start()方法建立与worker间的连接
        if (typeof Worker === "undefined") {
          alert('当前浏览器不支持webworker')
        } else {
          let worker = new SharedWorker('worker.js')
          worker.port.addEventListener('message', (e) => {
            console.log('来自worker的数据:', e.data)
          }, false)
          worker.port.start()
          window.worker = worker
        }
    // 获取和发送消息都是调用postMessage方法,我这里约定的是传递'get'表示获取数据。
    window.worker.port.postMessage('get')
    window.worker.port.postMessage('发送信息给worker')
  • 相关阅读:
    bzoj3505 数三角形 组合计数
    cogs2057 殉国 扩展欧几里得
    cogs333 荒岛野人 扩展欧几里得
    bzoj1123 BLO tarjan求点双连通分量
    poj3352 road construction tarjan求双连通分量
    cogs1804 联合权值 dp
    cogs2478 简单的最近公共祖先 树形dp
    cogs1493 递推关系 矩阵
    cogs2557 天天爱跑步 LCA
    hdu4738 Caocao's Bridge Tarjan求割边
  • 原文地址:https://www.cnblogs.com/cangqinglang/p/10635707.html
Copyright © 2011-2022 走看看