EventSource VS 轮询

一、EventSource

  • EventSource(Server-sent events)简称SSE用于向服务端发送事件,它是基于http协议的单向通讯技术,以text/event-stream格式接受事件,如果不关闭会一直处于连接状态,直到调用EventSource.close()方法才能关闭连接;
  • EvenSource本质上也就是XHR-streaming只不过浏览器给它提供了标准的API封装和协议。
  • 由于EeventSource是单向通讯,所以只能用来实现像股票报价、新闻推送、实时天气这些只需要服务器发送消息给客户端场景中。
  • EventSource虽然不支持双向通讯,但是在功能设计上他也有一些优点比如可以自动重连接,event IDs,以及发送随机事件的等功能。
  • EventSource 案例
    浏览器端代码:
// 实例化 EventSource 参数是服务端监听的路由
var source = new EventSource('/EventSource-test')
source.onopen = function (event) { // 与服务器连接成功回调
  console.log('成功与服务器连接')
}
// 监听从服务器发送来的所有没有指定事件类型的消息(没有event字段的消息)
source.onmessage = function (event) { // 监听未命名事件
  console.log('未命名事件', event.data)
}
source.onerror = function (error) { // 监听错误
  console.log('错误')
}
// 监听指定类型的事件(可以监听多个)
source.addEventListener("myEve", function (event) {
  console.log("myEve", event.data)
})

EventSource规范字段

  • event:事件类型,如果指定了该字段,则在客户端接收到该条消息时,会在当前的EventSource对象上触发一个事件,事件类型就是该字段的字段值,你可以使用addEventListener()方法在当前EventSource对象上监听任意类型的命名事件,如果该条消息没有event字段,则会触发onmessage属性上的事件处理函数。
  • data:消息的数据字段,如果该消息包含多个data字段,则客户端会用换行符把他们连接成一个字符串来处理
  • id:事件ID,会成为当前EventSource对象的内部属性“最后一个事件ID”的属性值;
  • retry:一个整数值,指定了重新连接的时间(单位为毫秒),如果该字段不是整数,则会被忽略。

EventSource属性

  • EventSource.onerror:是一个 EventHandler,当发生错误时被调用,并且在此对象上派发 error 事件。
  • EventSource.onmessage:是一个 EventHandler,当收到一个 message事件,即消息来自源头时被调用。
  • EventSource.onopen:是一个 EventHandler,当收到一个 open 事件,即连接刚打开时被调用。
  • EventSource.readyState (只读):一个 unsigned short 值,代表连接状态。可能值是CONNECTING (0), OPEN (1), 或者 CLOSED (2)。
  • EventSource.url (只读): 一个DOMString,代表源头的URL。

EventSource 通讯过程

在这里插入图片描述

缺点

  1. 因为是服务器->客户端的,所以它不能处理客户端请求流
  2. 因为是明确指定用于传输UTF-8数据的,所以对于传输二进制流是低效率的,即使你转为base64的话,反而增加带宽的负载,得不偿失。

二、轮询

  1. Poling: 是一种简单粗暴,同样也是一种效率低下的实现“实时”通讯方案,这种方案的原理就是定期向服务器发送请求,主动拉取最新的消息队列。
  • 客户端代码:
function Polling() {
    fetch(url).then(data => {
        // somthing
    }).catch(err => {
        console.log(err);
    });
}
//每5s执行一次
setInterval(polling, 5000);

在这里插入图片描述
这种轮询方式比较适合服务器信息定期更新的场景,如天气预报股票行情等,每隔一段时间会进行更新,且轮询间隔的服务器更新频率保持一致是比较理想的方式,但很多多时候会因网络或者服务器出现阻塞早场事件间隔不一致。

  • 优点: 可以看到实现非常简单,它的兼容性也比较好的只要支持http协议就可以用这种方式实
  • 缺点: 资源浪费:比如轮询的间隔小于服务器信息跟新频率,会浪费很多HTTP请求,消耗宝贵的CPU时间和带宽。
    容易导致请求轰炸:例如当服务器负载比较高时,第一个请求还没有处理完,这时第三、第四个请求接踵而来,无用的额外请求对服务器端进行了轰炸。
  1. Loop Polling: 这是一种优化的轮询方式,称为长轮询,sockjs就是使用的这种轮询方式,长轮询值的是浏览器发送一个请求到服务器,服务器只有在有可用的新数据时才会响应:
  2. function LongPolling() {
  • 客户端代码:
function LongPolling() {
    fetch(url).then(data => {
        LongPolling();
    }).catch(err => {
        LongPolling();
        console.log(err);
    });
}
LongPolling();

在这里插入图片描述
客户端向服务器发送一个消息获取请求时,服务器会将当前的消息队列返回给客户端,然后关闭连接。当消息队列为空的时,服务器不会立即关闭连接,而是等待指定的时间间隔,如果在这个时间间隔内没有新的消息,则由客户端主动超时关闭连接。
相比Polling,客户端的轮询请求只有在上一个请求连接关闭后才会重新发起。这就解决了Polling的请求轰炸问题。服务器可以控制的请求时序,因为在服务器未响应之前,客户端不会发送额为的请求。

  • 优点: 长轮询和短轮询比起来,明显减少了很多不必要的http请求次数,相比之下节约了资源。
  • 缺点: 连接挂起也会导致资源的浪费。

三、EventSource VS 轮询

轮询(Polling)长轮询(Long-Polling)EventSource
通信协议httphttphttp
触发方式client(客户端)client(客户端)client、server(客户端、服务端)
优点兼容性好容错性强,实现简单比短轮询节约f服务器资源实现简便,开发成本低
缺点安全性差,占较多的内存资源与请求数量,容易对服务器造成压力,请求时间间隔容易导致不一致安全性差,占较多的内存资源与请求数,请求时间间隔容易导致不一致只适用高级浏览器,老版本的浏览器不兼容
延迟非实时,延迟取决于请求间隔非实时,延迟取决于请求间隔非实时,默认3秒延迟,延迟可自定义

四、总结

通过对上面两种对通讯技术比较,可以从不同的角度考虑;

  • 兼容性: 短轮询 > 长轮询 > EventSource
  • 性能:EvenSource > 长轮询 > 短轮询
  • 服务端推送:EventSource > 长连接 (短轮询基本不考虑)

参考

https://juejin.im/post/5d8fffc1f265da5b7d69034b
https://zhuanlan.zhihu.com/p/72739758
https://www.jianshu.com/p/ef054d3d1b62

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值