eventsouce + koajs打造消息系統
之前寫過兩篇文章,分別是 《前端搶后端飯碗 — Node.js + Socket.io 制作簡易聊天室》 和 《koa + socket.io 制作簡易聊天室》 ,實質上都是利用了瀏覽器的websocket屬性進去前后端的消息交流。今天我們要介紹另外一種比較新但更為簡潔的消息傳輸方式,eventsource。
下面是關于eventsource的瀏覽器支持情況。除了IE和Opera Mini之后,其它瀏覽器的支持情況良好。除了瀏覽器的兼容性問題之外,eventsource其實 寫起來更為簡潔方便。
首先是前端的代碼:
var evtSource = new EventSource ( "xxxxxxxxxx" ) ; evtSource . onmessage = function ( e ) { var res = JSON . parse ( e . data ) ; // 其它操作 } |
前端代碼只需要通過onmessage事件就可以獲得后臺傳過來的數據。或者,可以監聽其它的事件,如下:
evtSource . addEventListener ( "ping" , function ( e ) { //其它操作 } , false ) ; |
至于后臺的代碼,網上流傳是大部份是php的版本。甚至連MDN上的都是。我們AlloyTeam的 iPresst 則使用了koajs開發,因此也使用js開發我們的消息系統。將status設為200是必不可少的,另外也需要設置content-type, connection, cache-control的字段。access-control-allow-origin是可選的,規定什么地址的請求會被允許。
exports . msg = function * ( ) { const response = { retcode : 0 , count : 0 , } ; // 數據庫操作 this . status = 200 ; this . set ( 'Content-Type' , 'text/event-stream' ) ; this . set ( 'Connection' , 'keep-alive' ) ; this . set ( 'Cache-Control' , 'no-cache' ) ; this . set ( 'Access-Control-Allow-Origin' , '*' ) ; // 延遲10秒 let r = 'retry: 10000\n' ; r += 'data: {"count": ' + JSON . stringify ( response . count ) + '}\n\n' ; this . body = r ; } ; |
后臺傳回來的消息就需要如下的格式:
id : 1 event: ping data : { count : 0 } retrey : 10000 |
字段 (參考 《使用服務器發送事件》 )
規范中規定了下面這些字段:
event事件類型.如果指定了該字段,則在客戶端接收到該條消息時,會在當前的EventSource對象上觸發一個事件,事件類型就是該字段的字段值,你可以使用addEventListener()方法在當前EventSource對象上監聽任意類型的命名事件,如果該條消息沒有event字段,則會觸發onmessage屬性上的事件處理函數.data消息的數據字段.如果該條消息包含多個data字段,則客戶端會用換行符把它們連接成一個字符串來作為字段值.id事件ID,會成為當前EventSource對象的內部屬性”最后一個事件ID”的屬性值.retry 一個整數值,指定了重新連接的時間(單位為毫秒), 如果該字段值不是整數,則會被忽略. 也就是說,你希望后臺每幾毫秒給前臺傳消息,那就填多少毫秒。