浏览器多个标签页之间的通信

一、WebSocket

  • WebSocket是HTML5新增的协议,它在浏览器和服务器之间建立一个不受限的双向通信的通道,比如说,服务器也可以随时发送消息给浏览器。
  • WebSocket是建立在TCP协议之上的。TCP协议本身就实现了全双工通信,但是HTTP协议的请求-应答机制限制了全双工通信。WebSocket连接建立以后,接下来的通信就不使用HTTP协议了,直接互相发数据。
  • 安全的WebSocket连接机制和HTTPS类似。
    首先,浏览器用wss://xxx创建WebSocket连接时,会先通过HTTPS创建安全的连接,然后,该HTTPS连接升级为WebSocket连接,底层通信走的仍然是安全的SSL/TLS协议。

WebSocket连接必须由浏览器发起,特点
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

二、SharedWorker

SharedWorker是HTML5新引入的,一种可以共享的Web Worker。
消息传递:普通的Web Worker通过onmessage监听事件和postMessage传递数据

// 初始化一个普通的worker线程执行计算任务
let worker = new Worker('workers.js');
...
button.addEventListener('click', function () {
    // 向worker传递消息
    worker.postMessage('start');
});
worker.onmessage = function (messageEvent) {
    alert('计算结束,结果为' + messageEvent.data + ',用时' + (new Date() - time) + 'ms'); 
}
...
//终止
worker.terminate();

shareWorker可以创建共享线程,即不同的页面使用同一个ShareWorkder,当所有的页面都关闭之后该线程会随之被结束。
消息传递:通过shareWorker.port 传递,使用方法与普通worker类似

let worker = new SharedWorker('sharedworkers.js');
// 传递strat指令
worker.port.postMessage('start');
// 接收子线程的数据
worker.port.onmessage = function (val) {
    timeDom.innerHTML = val.data
}

如果通过addEventListener绑定message事件的话(而不是.onmessage)这时候需要手动的调用 port 的 .start()方法。

worker.port.start();
worker.port.addEventListener('message', function(e) {
    // ... 
});

可以通过对onconnect事件获取到新的shareWorker的连接,然后在connect的参数中的ports字段我们可以拿到MessageEvent,这时候我们就可以使用 .onmessage 和 .postMessage 来处理和传递我们的数据了。

// sharedworkers.js
onconnect = function (e) {
    // 通过 e.ports 拿到 port
    var port = e.ports[0];

    // port.onmessage 监听父线程的消息
    port.onmessage = function () {
        // port.postMessage 向父线程传递消息
        port.postMessage(a++)
    }
}

注意:SharedWorker可以被多个window共同使用,但必须保证这些标签页都是同源的

三、localstorage

localstorage是浏览器多个标签共用的存储空间,所以可以用来实现多标签之间的通信(ps:session是会话级的存储空间,每个标签页都是单独的)。

//页面A发送事件
function sendMsg(text) {
    window.localStorage.setItem('msg',text);
}

//页面B接收事件
window.addEventListener('storage', function (evt) {
    if(evt.key==='msg')
       console.log(evt.newValue);
});

onstorage以及storage事件,针对都是非当前页面对localStorage进行修改时才会触发,当前页面修改localStorage不会触发监听函数。然后就是在对原有的数据的值进行修改时才会触发,比如原本已经有一个key会a值为b的localStorage,你再执行:localStorage.setItem('a', 'b')代码,同样是不会触发监听函数的。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容