实现多页签通讯的几种方法

实现多页签通讯的几种方法:

  • websocket协议
  • localstorage、cookie
  • SharedWorker(HTML5新特性)

websocket协议:

  • webSoket用来实现双向通信,客户端和服务端实时通信。
  • webSoket优点和缺点:
    1. 优点:对于前端来说,使用简单,功能灵活,如果部署了webSocket服务器,可以实现实时通信。
    1. 缺点:需要服务端技术的支持,如果websocket数据量比较大的话,会严重消耗服务器的资源。

websocket服务器端搭建

//初始化一个node项目:node init,一路确认就可以,文件夹会自动创建一个package.json文件
// 下载ws文件    npm i -save ws
//获得WebSocketServerr类型
var WebSocketServer = require('ws').Server;
//创建WebSocketServer对象实例,监听指定端口
var wss = new WebSocketServer({ port:8080 });
//创建保存所有已连接到服务器的客户端对象的数组
var clients=[];

//为服务器添加connection事件监听,当有客户端连接到服务端时,立刻将客户端对象保存进数组中
wss.on('connection', function (client) {
      console.log("一个客户端连接到服务器")
      if(clients.indexOf(client)===-1){//如果是首次连接
            clients.push(client) //就将当前连接保存到数组备用
            console.log("有"+clients.length+"客户端在线")
       //为每个client对象绑定message事件,当某个客户端发来消息时,自动触发
       client.on('message',function(msg){
             console.log('收到消息'+msg)
            //遍历clients数组中每个其他客户端对象,并发送消息给其他客户端
            for(var c of clients){
                  if(c!=client){//把消息发给别人
                        c.send(msg);
                  }
            }
       })

 }
})

发送信息的标签页

<!DOCTYPE html>
<html lang="en">
<head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
</head>
<body>
            <!-- 这个页面是用来发送信息的 -->
            <input type="text" id="msg">
            <button id="send">发送</button>
      <script>
                //建立到服务端webSoket连接
               var ws=new WebSocket("ws://localhost:8080")      
               send.onclick=function(){
                     if(msg.value.trim()!=''){//如果msg输入框内容不是空的
                     ws.send(msg.value.trim())  //将msg输入框中的内容发送给服务器
                     }
               }               
      </script>
</body>
</html>

接收信息的标签页

<!DOCTYPE html>
<html lang="en">
<head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
</head>
<body>
            <!-- 这个标签页是用来接收信息的 -->
      <h1 >收到的消息:<p id="recMsg"></p></h1>
      <script>
            //建立到服务端webSoket连接
             var ws=new WebSocket("ws://localhost:8080") 
             //当连接被打开时,注册接收消息的处理函数
             ws.onopen=function(event) {
            //当有消息发过来时,就将消息放到显示元素上
                   ws.onmessage=function(event) {
                   recMsg.innerHTML=event.data;  
                   }   
  
            }
             
      </script>
</body>
</html>

localstorage、cookie:

  • localstorage是浏览器多个标签共用的存储空间,所以可以用来实现多标签之间的通信(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(HTML5新特性):

  • 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.js和index.html在同一目录。

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

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

// sharedWorker所要用到的js文件,不必打包到项目中,直接放到服务器即可
    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')
  • 页面A发送数据给worker,然后打开页面B,调用window.worker.port.postMessage(‘get’),即可收到页面A发送给worker的数据。

参考1.
参考2.
参考3.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值