之前写过两篇文章,分别是 《前端抢后端饭碗 — 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
EventSource
对象的内部属性”最后一个事件ID”的属性值. retry