# 浏览器窗口间通信 浏览器多个标签页窗口间通信,主要是指的同源的多个页面间的通信,主要方法有本地存储通信、`Web Worker`通信、`Web Socket`通信。 ## 本地存储通信 通过浏览器对于同源页面本地存储是共享的策略实现通信,主要可以使用`localStorage`、`cookie`、`indexDB`,注意对于`sessionStroage`是在同一会话有效的,在`MDN`中提到,通过点击链接或者使用`window.open`打开的新标签页之间是属于同一个`session`的,新的标签页会继承上一级会话的`sessionStroage`,但新开一个标签页总是会初始化一个新的`session`,即使是同源的,它们也不属于同一个`session`。 ### localStorage ```javascript // 页面A localStorage.setItem('msg', Math.random()); ``` ```javascript // 页面B window.addEventListener("storage", function (e) { console.log(e); }) // onstorage事件 // 非当前页面对localStorage进行修改时才会触发,当前页面修改localStorage不会触发监听函数 // 在对原有的数据的值进行修改时才会触发监听函数,当新设值与原有值相同时不会触发。 ``` ### cookie ```javascript // 页面A document.cookie = "msg=1;path=/"; ``` ```javascript // 页面B function getCookie(key){ var cookies = {}; document.cookie.replace(/\s*/g,"").split(";").forEach((v) => { let unit = v.split("="); cookies[unit[0]] = unit[1]; }) return cookies[key]; } setInterval(() => { console.log(getCookie("msg")); }, 1000); ``` ### IndexedDB ```javascript // 页面A var db = null; var request = indexedDB.open("message"); request.onsuccess = (e) => db = e.target.result; request.onupgradeneeded = function(event) { db = event.target.result; if (!db.objectStoreNames.contains('message')) { db.createObjectStore('message', { keyPath: 'key' }); } }; function setData(data){ var transaction = db.transaction(['message'], 'readwrite'); var store = transaction.objectStore(['message']); var requestData = store.put({ key: "msg", info: data}); requestData.onsuccess = function(e) { console.log(e.target.result); }; }; setTimeout(() => setData(1),1000); ``` ```javascript // 页面B var db = null; var request = indexedDB.open("message"); request.onsuccess = (e) => db = e.target.result; function readMsg(){ var transaction = db.transaction(['message']); var objectStore = transaction.objectStore('message'); var requestResult = objectStore.get('msg'); requestResult.onsuccess = function(event) { console.log(requestResult.result.info); }; } setTimeout(readMsg, 3000); ``` ## Web Worker `HTML5`中的`Web Worker`可以分为两种不同线程类型,一个是专用线程`Dedicated Worker`,一个是共享线程`Shared Worker`。 `Dedicated Worker`直接使用`new Worker()`即可创建,这种`webworker`是当前页面专有的。 `SharedWorker`可以被多个`window`、标签页、`iframe`共同使用,但必须保证这些标签页都是同源的。 ```javascript // 页面A var worker = new SharedWorker('worker.js'); worker.port.start(); worker.port.postMessage(1); ``` ```javascript // 页面B var worker = new SharedWorker('worker.js'); worker.port.start(); worker.port.onmessage = function(event){ console.log(event.data); }; ``` ```javascript // worker.js var portArr = []; onconnect = function(e) { var port = e.ports[0]; if(portArr.indexOf(port) === -1) portArr.push(port); port.onmessage = function(e) { portArr.forEach( v => { v.postMessage(e.data); }) } } ``` ## Web Socket 使用`Web Socket`将服务器作为数据中转站进行数据传输,可以实现浏览器窗口间通信,但是比较耗费服务器资源。`WebSocket`是`HTML5`开始提供的一种在单个`TCP`连接上进行全双工通讯的协议。`WebSocket` 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 `WebSocket API`中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。在`WebSocket API`中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道,两者之间就直接可以数据互相传送。 * 握手阶段采用`HTTP`协议,在普通`HTTP`报文中包含了一些附加头信息,其中附加头信息`Upgrade: WebSocket`表明这是一个申请协议升级的`HTTP`请求。 * 建立在`TCP`协议基础之上,和`HTTP`协议同属于应用层。 * 可以发送文本,也可以发送二进制数据。 * 数据格式比较轻量,性能开销小,通信高效。 * 没有同源限制,客户端可以与任意服务器通信。 * 协议头标识符是`ws`,如果加密传输则为`wss`。 ## 每日一题 ``` https://github.com/WindrunnerMax/EveryDay ``` ## 参考 ``` https://github.com/lmk123/blog/issues/66 https://www.cnblogs.com/cloud-/p/10713213.html https://www.cnblogs.com/lalalagq/p/9921144.html ```