1. 首页
  2. 技术知识

前端实时通信的8种方式及其优缺点和实现方式

1.短轮询

短轮询的原理很简单,每隔一段时间客户端就发出一个请求,去获取服务器最新的数据,一定程度上模拟实现了即时通讯。

    优点:兼容性强,实现非常简单缺点:延迟性高,请求中有大半是无用,非常消耗带宽和服务器资源,影响性能应用: 二维码扫码确认、信息通知实现方式:

    借用定时器实现短轮询

  1. created(){
  2.         this.shortPolling = setInterval(functiоn(){
  3.             that.getRuset()
  4.         },5000)
  5. },
  6. getResult(){
  7.         var that = this
  8.         this.$axios(‘xxx,’,post).then(res=>{
  9.                 if(res.code === 200){//拿到想要的结果
  10.                          …
  11.                          //定时器是否清除由业务场景决定
  12.                          clearInterval(this.shortPolling)
  13.                 }
  14.         })
  15. }

复制代码
2.comet(长轮询、长连接)

comet有两种主要实现手段,一种是基于 AJAX 的长轮询(long-polling)方式,另一种是基于 Iframe 及 htmlfile 的流(streaming)方式,通常被叫做长连接。

具体两种手段的操作方法请移步Comet技术详解:基于HTTP长连接的Web端实时通信技术


2.1、长轮询

客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。

    优点:兼容性好,在无消息的情况下不会频繁的请求,资源浪费较小缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护应用: webQQ、开心网、校内,Hi网页版、Facebооk IM等等实现方式:

    主要由后端hold住连接,我们就是正常的发送请求即可

  1. getResult(){
  2.         var that = this
  3.         this.$axios(‘xxx,’,post).then(res=>{
  4.                 if(res.code === 200){
  5.                         …
  6.                 }else{
  7.                         this.getResult()
  8.                 }
  9.                 …
  10.         })
  11. }

复制代码 正常来说我们前端会设置请求超时时间,那么我们就和后端约定,在超时范围内必须返回结果在前端即可。


2.2、长连接

在页面里嵌入一个隐蔵iframe,将这个隐蔵iframe的src属性设为对一个长连接的请求或是采用xhr请求,服务器端就能源源不断地往客户端输入数据。 此方法已经过时,我推荐使用,毕竟现在都已经放弃iframe

    优点:兼容性好,消息即时到达,不发无用请求缺点:服务器维护长连接消耗资源实例:Gmail聊天实现方式:

  1. //在vue中嵌入iframe
  2. <iframe ref=”iframe” v-show=”iframeShow”></iframe>
  3. watchIframe(){
  4.         //先找到iframe的窗口
  5.         this.iframeWin = this.$refs.iframe.contentWindow;
  6.         //向iframe发送信息,大括号内是发送的内容;
  7.         this.iframeWin.postMessage(
  8.              {
  9.               },”*”
  10.         );
  11.         //怎样监听iframe传过来的信息
  12.         window.addEventListener(“message”, this.handleMessage);
  13.         //获取iframe传过来的信息
  14.         handleMessage(res){
  15.           //res为传过来的信息
  16.          …//渲染页面
  17.         }
  18. }

复制代码
3.SSE 使用指南请看Server-Sent Events 教程

SSE(Server-Sent Event,服务端X事件)是一种允许服务端向客户端X新数据的HTML5技术

    优点:基于HTTP而生,因此不需要太多改造就能使用,使用方便,而websocket非常复杂,必须借助成熟的库或框架缺点:基于文本传输效率没有websocket高,不是严格的双向通信,客户端向服务端发送请求无法复用之前的连接,需要重新发出独立的请求,并且不兼容IE

  1. source.addEventListener(‘open’, functiоn (event) {
  2.   // …
  3. }, false);
  4. //客户端收到服务器发来的数据,就会触发message事件,可以在onmessage属性的回调函数。
  5. source.addEventListener(‘message’, functiоn (event) {
  6.   var data = event.data;
  7.   // handle message
  8. }, false);
  9. //如果发生通信错误(比如连接中断),就会触发error事件,可以在onerror属性定义回调函数。
  10. source.addEventListener(‘error’, functiоn (event) {
  11.   // handle error event
  12. }, false);
  13. //close方法用于关闭 SSE 连接。
  14. source.close();

复制代码 我们也可以自定义事件,Server-Sent Events 教程里都有明确的使用方法


4.Websocket

Websocket是一个全新的、独立的协议,基于TCP协议,与http协议兼容、却不会融入http协议,仅仅作为html5的一部分,其作用就是在服务器和客户端之间建立实时的双向通信。

    优点:真正意义上的实时双向通信,性能好,低延迟缺点:独立与http的协议,因此需要额外的项目改造,使用复杂度高,必须引入成熟的库,无法兼容低版本浏览器实现方式:

浏览器为 HTTP 通信提供了 XMLHttpRequest 对象,同样的,也为 WebSocket 通信提供了一个通信操作接口:WebSocket。

  1. var ws = new WebSocket(“wss://echo.websocket.org”);
  2.   // 当连接建立成功,触发 open 事件
  3.   ws.onopen = functiоn(evt) {
  4.     console.log(“建立连接成功 …”);
  5.     // 连接建立成功以后,就可以使用这个连接对象通信了
  6.     // send 方法发送数据
  7.     ws.send(“Hello WebSockets!”);
  8.   };
  9.   // 当接收到对方发送的消息的时候,触发 message 事件
  10.   // 我们可以通过回调函数的 evt.data 获取对方发送的数据内容
  11.   ws.onmessage = functiоn(evt) {
  12.     console.log(“接收到消息: ” + evt.data);
  13.     // 当不需要通信的时候,可以手动的关闭连接
  14.     // ws.close();
  15.   };
  16.   // 当连接断开的时候触发 close 事件
  17.   ws.onclose = functiоn(evt) {
  18.     console.log(“连接已关闭.”);
  19.   }

复制代码
5.Web Worker

Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行

    优点:实现多线程环境,摆脱了js的单线程缺点:无法访问DOM节点;无法访问全局变量或是全局函数;无法调用alert()或者confirm之类的函数;无法访问window、document之类的浏览器全局变量;

    注意:
    Web Worker中的Javascript依然可以使用setTimeout(),setInterval()之类的函数,也可以使用XMLHttpRequest对象来做Ajax通信实例:大数据的处理;高频的用户交互:实现方式:

Web workers可分为两种类型:专用线程、共享线程。

专用线程随当前页面的关闭而结束;这意味着专用线程只能被创建它的页面访问。

与之相对应的共享线程可以被多个页面访问。


5.1、专用线程

使用 onmessage() , postmessage()通信

  1. /** 主线程 **/
  2. //注册专用线程
  3. let worker = new Worker (‘worker.js’)
  4. worker.onmessage = (e) => {
  5.   console.log(e.data) // I post a message to main thread
  6. }
  7. worker.postMessage(‘main thread got a message’)
  8. /**  子线程 worker.js  **/
  9. onmessage = (e) => {
  10.     console.log(e.data) // main thread got a message
  11. }
  12. postMessage(‘I post a message to main thread’)
  13. // 在主线程中终止
  14. worker.terminate()
  15. // 在子线程中终止自身
  16. self.close()

复制代码
5.2、共享线程

SharedWorker需要用到port属性,接收需要先connect

  1. //注册共享线程
  2. let worker = new SharedWorker(“sharedworker.js”);
  3. /**  主线程  **/
  4. worker.port.onmessage = functiоn(e){}
  5. worker.port.postMessage(‘data’);
  6. /** 子线程 **/
  7. addEventListener(‘connect’, functiоn(event){
  8.     var port = event.ports[0]
  9.     //接收
  10.     port.onmessage = functiоn(event){
  11.         console.log(event.data);
  12.     };
  13.     //发送
  14.     port.postMessage(“data”);
  15.     port.start();
  16. });
  17. // 在主线程中终止
  18. worker.terminate()
  19. // 在子线程中终止自身
  20. self.close()

复制代码 两种方式的错误监听同SSE一样

  1. worker.addEventListener(“error”, functiоn(evt){  
  2.         alert(“Line #” + evt.lineno + ” – ” + evt.message + ” in ” + evt.filename);  
  3.         }, false);  
  4.         worker.postMessage(10000);  
  5. });  

复制代码
6.Service workers

Service workers 本质上充当Web应用程序与浏览器之间的X服务器,也可以在网络可用时作为浏览器和网络间的X,创建有效的离线体验。 它是 Web Worker 的一个类型

    优点:可以秒开或者离线访问缺点:IE11 、Opera Mini 、IOS不支持应用:X通知 — 允许用户选择从网络应用程序及时更新。实现方式:

  1. // serviceWorker.js
  2. import { register } from ‘register-service-worker’
  3. if (process.env.NODE_ENV === ‘production’) {
  4.   register(‘service-worker.js’, {
  5.     ready () {
  6.       console.log(
  7.         ‘APP is being served from cache by a service worker.’
  8.       )
  9.     },
  10.     registered () {
  11.       console.log(‘Service worker has been registered.’)
  12.     },
  13.     cached () {
  14.       console.log(‘Content has been cached for offline use.’)
  15.     },
  16.     updatefound () {
  17.       console.log(‘New content is downloading.’)
  18.     },
  19.     updated () {
  20.       console.log(‘New content is available; please refresh.’)
  21.       window.location.reload(true)   // 这里需要刷新页面
  22.     },
  23.     offline () {
  24.       console.log(‘No internet connection found. App is running in offline mode.’)
  25.     },
  26.     error (error) {
  27.       console.error(‘Error during service worker registration:’, error)
  28.     }
  29.   })
  30. }

复制代码 在 plugins 加入

  1. plugins: [
  2.     new SWPrecacheWebpackPlugin({
  3.       cacheId: ‘my-project-name’,
  4.       filename: ‘service-worker.js’,
  5.       staticFileGlobs: [‘dist/**/*.{js,html,css}’],
  6.       minify: true,
  7.       stripPrefix: ‘dist/’
  8.     }),
  9.     new WebpackPwaManifest({
  10.       name: ‘My Progressive Web App’,
  11.       short_name: ‘MyPWA’,
  12.       description: ‘My awesome Progressive Web App!’,
  13.       background_color: ‘#ffffff’,
  14.       crossorigin: ‘use-credentials’, //can be null, use-credentials or anonymous
  15.       icons: [
  16.         {
  17.           src: path.resolve(‘src/assets/icon.png’),
  18.           sizes: [96, 128, 192, 256, 384, 512] // multiple sizes
  19.         },
  20.         {
  21.           src: path.resolve(‘src/assets/large-icon.png’),
  22.           size: ‘1024×1024’ // you can also use the specifications pattern
  23.         }
  24.       ]
  25.     }),
  26.     // …
  27. ]

复制代码 这个时候打包出来的代码根目录里面多了个 service-worker.js ,html文件里面 pwa 相关元素也加上了。

在入口 main.js 引入该文件:

  1. import ‘./serviceWorker’

复制代码
7、Flash Socket

在页面中内嵌入一个使用了Socket类的 Flash 程序JavaScript通过调用此Flash程序提供的Socket接口与服务器端的Socket接口进行通信,JavaScript在收到服务器端传送的信息后控制页面的显示。 一般用在网络游戏中,web端基本不适用,加上早在 2022 年 7 月,Flash 的娘家 Adobe 已宣布在 2022年 底终止对 Flash 的支持。各个浏览器也在2022年底左右终止对 Flash 的支持

    优点:实现真正的即时通信,而不是伪即时。缺点:客户端必须安装Flash插件;非HTTP协议,无法自动穿越防火墙。实例:网络互动游戏。实现方式:因为都已经抛弃了,加上我并非游戏类前端,我就没了解Flash实现方式,有兴趣的小伙伴可以自行去研究一下

8、总结

    我在实际项目中,只使用过短轮询和长轮询,其他的实时通讯方法并没有真正使用过(业务场景并没有其他需求)而且后端也给不了太多支持来实现是否可行。长轮询与服务器的通信会比短轮询更实时,短轮询是在采用定时器,定时器就有时间差,比如我们定时5秒钟。可能一秒钟内我们就实现了数据通信,那么会有4秒的等待时间。而长轮询就可以这个顾虑。是否可以使用回调递归实现实时通信,可以,他类比短轮询,但是回调递归并发量太大了,很容易造成服务器死机,并且消耗宽带影响到前端性能,所以我们正常不会使用回调递归实现,而且回调递归也不叫作短轮询。为了方便以后使用,并单纯的学习。此次总结是看了N篇文章的结合,有不足之处,敬请指出。

更多关于
前端实时通信方式及其优缺点和实现方式请查看下面的相关链接

原创文章,作者:starterknow,如若转载,请注明出处:https://www.starterknow.com/108296.html

联系我们