前言ajax我们已经讲过了。浏览器推送数据呢?那么在这篇文章中,我们就来说说服务端推送功能。轮询假设现在需要做一个足球比赛的直播页面,主播在后台以文字的方式进行比赛直播,那么这就要求解说数据尽可能实时的到达浏览器,那么我们如何做呢?解决这个问题?最容易想到的就是用ajax轮询,写一个定时器,每隔几秒就去后台请求数据,当然可以,但是这种方式不是很优雅。因为浏览器每次都需要主动询问服务器是否有数据。如果服务端有数据,主动告诉浏览器不是更好吗?如何让服务端自己主动推送数据?让我们先实现它。服务器的代码如下:图1如图1所示,我们使用express启动一个小服务。每当服务端收到请求并响应时,都会将Content-type设置为text/event-stream,这是实现服务端推送的关键点,这次的链接是通过flow实现的,并且链接全程保持打开状态页面的生命周期!页面上的实现和普通的ajax类似,但也有一点不同,如图2。图2,获取数据时Status在3,因为这个链接一直是打开的。当你同时运行服务端和客户端代码时,你会发现浏览器控制台会一直打印123,此时我们就实现了服务端推送功能。SSE根据上面描述的服务器推送的特点,浏览器本身也实现了这样一个接口——SSE。下面看一下浏览器的使用方法,如下:图3如图3所示,使用EventSource创建一个实例对象,参数是stream实现的接口,下面绑定了几个事件,打开,其中将在连接后立即触发;message,服务端向客户端发送数据的默认事件,数据可以通过e.data获取;foo,自定义事件(SSE支持自定义事件);error,链接错误时触发。接下来我们看一下服务端的实现,如下图4所示,与图1中的代码类似,先启动服务端,再打开页面,看现象:图5从现象来看,我们已经意识到服务端推送符合预期,非常好!但是要注意图4中响应数据的写法,以data开头:会默认触发页面中的message事件,以\n\n结尾结束一次推送。如果不能写一行,可以用\nsplit;下面看看如何触发自定义事件,代码如下:图6图6,我们添加一行字符串-'event:'+事件名+'\n',这样会触发页面中的foo事件不是消息事件。现象如下:图7据说SSE有断开重连的能力。我们试试看是不是真的?图8图8证明传言属实。当服务关闭时,页面会不断尝试重新连接,当服务再次启动时,页面会立即链接。如果服务端在发送数据的时候加上一行字符串-"retry:"+time+"\n\n",可以设置断线重连的时间间隔,这个就不演示了。到目前为止,推送仍然是无状态的。如果链接断开再重新连接,服务器不知道之前推送了哪些数据。为了解决这个问题,可以在每次推送的时候加上一行字符串——“id:”+序列号+“\n”,如下:图9我们再来看一下现象,如下:图10序列号可以通过事件对象的lastEventId属性在页面上获取。下次重连时,浏览器会把最后一次的主序号放在请求头的Last-Event-ID字段中,这样服务器就可以通过这个请求头属性获取之前的数据推送状态。图11总结本文主要讲解SSE的使用方法。它是浏览器自带的API。如果浏览器不兼容,我们也可以让它兼容。从上面的介绍,我们可以看出它是单向的。连接后只能由服务器推送到浏览器,所以非常适合只查询的需求,比如球赛直播、股票直播的需求。
