如今先後端通信的經常使用的方式有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內容。