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')
  • 相关阅读:
    JavaWeb核心之Servlet
    Http&Tomcat
    XML&反射
    JDBC连接池和DBUtils
    JDBC
    testng依赖
    java mysql
    eclipse自动补全的设置
    java Logger 的使用与配置
    python数据持久存储:pickle模块的基本使用
  • 原文地址:https://www.cnblogs.com/cangqinglang/p/10635707.html
Copyright © 2011-2022 走看看