当前位置:首页 > 技术分析 > 正文内容

详解前端如何让服务器主动向浏览器推送数据

ruisui883个月前 (02-19)技术分析10

前言

前面我们已经聊了ajax,它的特点是浏览器必须先发起请求,服务器才能给出对应的响应,想一想能不能让服务器主动向浏览器推送数据呢?那么这篇文章我们来聊一聊服务器推送功能。

轮询

假设你现在需要去做一个球赛直播页面,一个主播在后台文字直播比赛,那么这就要求解说数据尽可能的实时到达浏览器,那么我们如何解决呢?

最容易想到的就是用ajax轮询,写个定时器,每隔几秒钟去后端请求一次数据,这当然是可以的,但是这种方式并不是很优雅。因为浏览器每次需要主动去询问服务器有没有数据,如果反过来服务器有数据能主动告之浏览器岂不是更好?

初识推送

那么如何能让服务器自己主动推送数据呢?下面我们先实现一下服务端的代码,如下:

如图1,我们用express起了一个小服务,每当服务器接收到请求在响应时就会把Content-type设置为text/event-stream,这是实现服务器推送的关键,它表示这次链接采用流实现并且整个页面生命周期都保持这一个链接的打开状态!

页面上的实现和普通ajax类似,但也有点不同,如下

如图2,获取数据时的状态是在3,因为此链接一直处于打开状态。

当你同时运行服务端和客户端的代码时,你会发现浏览器控制台会一直打印123,此刻我们就已经实现了服务器推送的功能。

SSE

根据上面介绍的服务器推送的特点,浏览器自身也实现了这样的接口——SSE。

我们先看一下浏览器端如何使用,如下:

如图3,使用EventSource创建一个实例对象,参数是流实现的接口,下面绑定了几个事件,

  • open,当连接上之后就会立即触发;
  • message,服务器向客户端发送数据的默认事件,通过e.data可以获取到数据;
  • foo,自定义事件(SSE支持自定义事件);
  • error,当链接发生错误时触发。

下面我们再看一下服务端实现,如下:

如图4所示,和图1中的代码雷同,先起一下服务端,再打开页面,看一下现象:

从现象看我们已经实现了服务器推送,符合预期,很好!但是要注意图4中响应数据时的写法,以data: 开头会默认触发页面中message事件,以\n\n结尾结束一次推送,如果一行写不下可以用\n分割;

下面我们看看如何触发自定义事件,代码如下:

如图6,我们加一行字符串——'event:' + 事件名 + '\n',这样就会触发页面中的foo事件而不是message事件,现象如下:

据说SSE具有断线重连能力,我们试一下,看看是真是假?

图8证明传言不虚,当把服务关掉,页面在不停的尝试重连,当服务再次启动,页面就会立马链接上。如果服务端在发送数据时加一行字符串——"retry: " + 时间 + "\n\n" ,可以设置断开后重新再链接的间隔时间,这个就不演示了。

到目前为止,推送还是无状态的,如果链接断开了,再次重连,服务器是不知道先前已经推送了什么数据,为了解决这个问题,在每次推送时可以加一行字符串——"id: " + 序号 + "\n",如下:

我们再来看一下现象,如下:

这个序号在页面上用事件对象的lastEventId属性可以拿到,当下一次重新连接时,浏览器会把最后一次序号放在请求头的Last-Event-ID字段中,所以服务端可以通过这个请求头属性获取之前数据推送的情况。

总结

这篇文章主要讲解SSE如何使用,它是浏览器自带的API,如果浏览器不兼容,我们也可以对它做兼容。从以上的介绍可以看出它是单向的,连接后只能是服务器向浏览器推送,所以它非常适合仅有查询的需求,像球赛直播、股票类的需求。

喜欢我的文章就关注我吧,有问题可以发表评论,我们一起学习,共同成长!

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/2074.html

标签: 前端服务器
分享给朋友:

“详解前端如何让服务器主动向浏览器推送数据” 的相关文章

K8s里我的容器到底用了多少内存?

作者:frostchen导语 Linux下开发者习惯在物理机或者虚拟机环境下使用top和free等命令查看机器和进程的内存使用量,近年来越来越多的应用服务完成了微服务容器化改造,过去查看、监控和定位内存使用量的方法似乎时常不太奏效。如果你的应用程序刚刚迁移到K8s中,经常被诸如以下问题所困扰:容器的...

neovim 0.9在win下配置 python开发环境

初级的一些配置点击下面链接查看neovim安装插件管理器neovim常用快捷键neovim python开发环境简易配置方法 (需要手动键入命令行 运行python)安装neovim python的模块pip install pynvim pip install jedi pip install n...

Vue2的16种传参通信方式

前言先直入主题列出有哪些传参方式,下面再通过事例一一讲解。props(父传子)$emit与v-on (子传父)EventBus (兄弟传参).sync与update: (父子双向)v-model (父子双向)ref$children与$parent$attrs与$listeners (爷孙双向)pr...

Vue Router 4 路由操作 - 路由导航

路由导航分为 声明式导航 和 编程式导航。通过 <router-link to="..."> 标签跳转的方式为声明式导航。通过 路由实例对象(router.push(...))跳转的为编程式导航。导航到不同的位置想要导航到不同的URL,使用 router.push 方法。...

VUE 技术栈

官网链接:https://cn.vuejs.org/什么是vue:渐进式JavaScript 框架vue-cli链接:https://cli.vuejs.org/vue-cli安装:npm install -g @vue/clivue -V创建一个项目:vue create xxxxxx模版语法:文...

vue开发微信小程序 - 登录组件

移动端登录功能抽象为通用组件,满足:不同移动端应用中一键登录功能复用支持多种登录:微信登录、H5、QQ登录登录组件使用//引用登录组件 import login from "../components/user/login.vue" export default { compone...