如今先后端通信的经常使用的方式有ajax,websocket,还有fetch。可是常常的咱们会接到一些需求,好比说后端要给前端发送一些通知,前端接收到通知以后,作出相应的操做,好比说发说说之类的,当本身的朋友发一个说说的话,他也但愿你这边的界面也要呈现出来,或者说当一个企业的管理员发送一个公告,你再你的电脑上面也要可以及时的响应出来,这样的需求我相信不少人都碰见过。前端
针对于上面的问题,咱们经常使用的方式就是用setInterval去作轮询或者是websocket,只是前者setInterval轮询这个中间的时间间隔须要考虑好,若是事件间隔较短,这对服务器的压力比较大,若是事件较长,则有些须要当即当即作出响应的方式是作不到的。后者的websocket相对来讲技技术要求有点高,实现起来比较复杂。node
因此就有如今的这种方式就是Server-sent Events,也就是说服务器端给前端浏览器发送事件的方式。使用Server-sent Events实际上是很是简单的。咱们只须要须要在服务器端将事件流发送给前端,而后前端接收到后端所传给的事件流,而后触发事件,这是事件的捕获和监听其实和前端的事件捕获和触发是同样的。因此对于前端人员来讲,这种处理方式是很是的简单的。web
Server-sent Events是包含在EventSoruce对象中。咱们能够经过建立一个EventSource对象,给对象中传入一个地址,也就是咱们请求服务器端发送事件的地址,就建立了连接,以下所示:ajax
var evtSource = new EventSource('/sse');
其中 '/sse' 是服务器端给的向前端发送事件的接口地址。经过get方式进行发送事件。json
若是事件发送地址存在跨域问题,则,咱们在建立EvenetSource对象的时候,须要制定具体的地址,好比说:后端
var evtSource = new EventSource('http://www.baidu.com', { withCredentials: true });
这个时候,咱们的事件接收器就算是建立好了,而后经过经过onmessage来接收后台传给前端的数据,也能够经过addEventListener去建立事件的监听,可是经过addEventListener建立的事件监听是须要后端的事件发送方发送相对应的事件,才可以进行触发的。跨域
var evtSource = new EventSource('/sse'); evtSource.onmessage = function (e) { console.log(e.data) }
也就是当后端发送的内容以后就会进行触发,而且将data给打印出来,首先要提出的的是,Server-sent Events 所发送的内容都是字符串的流并且是经过utf-8的编码格式的,若是后端但愿给前端发送一串json,也须要将json转化成相对应的字符串,而后在发送给前端,前端接收以后,再讲所发送的字符串转换成json,而后进行处理。浏览器
而后就是监听后端发送给前端的事件内容,不如说,咱们后端给前端sent一个testEvent事件,前端经过事件接收者,去触犯相对应的事件监听,所以就有了下面的工做流程服务器
var evtSource = new EventSource('/sse'); evtSource.addEventListener('testEvent', function (e) { console.log(e) })
上面代码是前端的接收事件的放,是否是很相似,就像咱们以前用的同样。websocket
var btn = document.getElementById('button') btn.addEventListener('click', funciont (e) { console.log(e) })
咱们看到了前端的处理方案,可是后端应该如何才能给咱们发送事件呢,
首先咱们发送内容是须要给前端设置一个mime为text/event-stream,而后在进行发送事件的内容,下面是相对应的node代码
router.get('/sse', (req, res, next)=> { res.writeHead(200, { 'Connection': 'keep-alive', 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' }); let data = { meg: '这是一个测试SSE的数据内容' }; setTimeout(() => { console.log(JSON.stringify(data)); res.write('data:' + JSON.stringify(data) + '\n\n'); }, 2000) })
这样就可以发送给前端一条消息,就可以触发前端的事件内容。
router.get('/sse', (req, res, next)=> { res.writeHead(200, { 'Connection': 'keep-alive', 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' }); let data = { meg: '这是一个测试SSE的数据内容' }; setTimeout(() => { console.log(JSON.stringify(data)); res.write('event: testEvent\n\n'); res.write('data:' + JSON.stringify(data) + '\n\n'); }, 2000) })
这个就是给前端发送图个testEvent,所传送的数据就是咱们的data内容。