本题主要考察多页应用中各个页签之间数据交互的技术手段。实现多页通讯主要有利用浏览器数据存储方式和服务器方式。浏览器数据存储的方式主要用本地存储方式解决。即调用 localStorage、Cookie 等本地存储方式。服务器方式主要使用 websocket 技术使多页签都监听服务器推送事件来获得其他页签发送的数据。
浏览器存储:
第一种——调用 localStorage
在一个标签页里面使用 localStorage.setItem(key,value)添加(修改、删除)内容;
在另一个标签页里面监听 storage 事件。 即可得到 localstorge 存储的值,实现不同标签页之间的通信。
在一个标签页调用localStorage.setItem(name,val)
保存数据localStorage.removeItem(name)
删除数据的时候会触发 ‘storage’事件。
在另外一个标签页监听 document 对象的 storage 事件,在事件 event 对象属性中获取信息
event 事件对象包含以下信息
- domain
- newValue
- oldValue
- key
标签页 1:
1 | <input id="name" /> |
标签页 2:
1 | <script type="text/javascript"> |
第二种——调用 cookie+setInterval()
将要传递的信息存储在 cookie 中,每隔一定时间读取 cookie 信息,即可随时获取要传递的信息。
在 A 页面将需要传递的消息存储在 cookie 当中
在 B 页面设置 setInterval,以一定的时间间隔去读取 cookie 的值。
- 调用 localstorage,cookies 等本地存储方式
- WebSocket、SharedWorker
- localstroge 另一个浏览器上下文被添加、删除或修改时,它都会触发一个事件,我们通过监听事件,控制它的值来进行页面信息通信。
- 注意 quirks:Safari 在无痕迹模式下设置 localstorge 值抛出 QuotExceededError 的异常。
页面 1:
1 | <input id="name" /> |
页面 2:
1 | <script type="text/javascript"> |
监听服务器事件
第一种 websocket 通讯
WebSocket 是全双工(full-duplex)通信自然可以实现多个标签页之间的通信。WebSocket 是 HTML5 新增的协议,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道,比如说,服务器可以在任意时刻发送消息给浏览器。为什么传统的 HTTP 协议不能做到 WebSocket 实现的功能?这是因为 HTTP 协议是一个请求-响应协议,请求必须先由浏览器发给服务器,服务器才能响应这个请求,再把数据发送给浏览器。也有人说,HTTP 协议其实也能实现啊,比如用轮询或者 Comet。这个机制的缺点一是实时性不够,二是频繁的请求会给服务器带来极大的压力。Comet 本质上也是轮询,但是在没有消息的情况下,服务器先拖一段时间,等到有消息了再回复。这个机制暂时地解决了实时性问题,但是它带来了新的问题:以多线程模式运行的服务器会让大部分线程大部分时间都处于挂起状态,极大地浪费服务器资源。另外,一个 HTTP 连接在长时间没有数据传输的情况下,链路上的任何一个网关都可能关闭这个连接,而网关是我们不可控的,这就要求 Comet 连接必须定期发一些 ping 数据表示连接“正常工作”。WebSocket 并不是全新的协议,而是利用了 HTTP 协议来建立连接。为什么 WebSocket 连接可以实现全双工通信而 HTTP 连接不行呢?实际上 HTTP 协议是建立在 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。
第二种 html5 浏览器的新特性 SharedWorker
普通的 webworker 直接使用 new Worker()即可创建,这种 webworker 是当前页面专有的。然后还有种共享 worker(SharedWorker),这种是可以多个标签页、iframe 共同使用的。SharedWorker 可以被多个 window 共同使用,但必须保证这些标签页都是同源的(相同的协议,主机和端口号)
首先新建一个 js 文件 worker.js,具体代码如下:
1 | // sharedWorker所要用到的js文件,不必打包到项目中,直接放到服务器即可 |
webworker 端(暂且这样称呼)的代码就如上,只需注册一个 onmessage 监听信息的事件,客户端(即使用 sharedWorker 的标签页)发送 message 时就会触发。
注意 webworker 无法在本地使用,出于浏览器本身的安全机制,所以我这次的示例也是放在服务器上的,worker.js 和 index.html 在同一目录。
因为客户端和 webworker 端的通信不像 websocket 那样是全双工的,所以客户端发送数据和接收数据要分成两步来处理。示例中会有两个按钮,分别对应的向 sharedWorker 发送数据的请求以及获取数据的请求,但他们本质上都是相同的事件–发送消息。
webworker 端会进行判断,传递的数据为’get’时,就把变量 data 的值回传给客户端,其他情况,则把客户端传递过来的数据存储到 data 变量中。下面是客户端的代码:
1 | // 这段代码是必须的,打开页面后注册SharedWorker,显示指定worker.port.start()方法建立与worker间的连接 |
明确考察点
什么是多页应用
两种浏览器存储方式实现多页签通讯
两种借助服务器方式实现多页通讯
回答思路
首先明确一下多页应用的应用场景,然后分别介绍浏览器存储方式和借助服务器方式实现多页通讯的实现关键技术。
相关扩展
- nodejs 快速搭建服务器