Server-Sent Events 服务端发送事件

SegmentFault

共 3744字,需浏览 8分钟

 ·

2021-03-15 20:24

作者:Riki一二三
来源:SegmentFault 思否社区



大多数时候,网页必须向服务器发送请求以接收新数据。服务端发送的事件,可以将消息推送到网页。


什么是SSE(Server-Sent Events)


  本质上,SSE使用户可以订阅实时数据流。
  每当此数据流更新时,用户都可以实时看到新事件。
  如果你知道Long-Polling或Web Socket那么你可能觉得它没什么大不了


SSE vs Web-Socket

  
Websocket是服务器之间的双向通信形式。
  它通常用于建立聊天室或多人视频游戏,因为这些应用程序场景需要服务器和客户端之间的持续通信。
  你可以将SSE视为单向websocket。只有服务器可以将消息发送到订阅的客户端。在许多Web应用程序中,Web套接字可能会过大。
  例如,商品的价格不需要双向通信。服务器仅需要单向通信来更新其所有客户端的价格。
  但是在客户端与服务端需要强交互的场景下,Web Socket仍是最佳选择

SSE vs Long-Polling


  长轮询是一种通信方法,客户端定期访问服务器获取新数据。
  适用于需要经过一定时间的计算或者人工干预的响应
  SSE通常用于快速生成事件的应用程序中,即时更新。
  长轮训虽然可以避免短轮训造成的服务端过载,但在服务端返回数据后仍需要客户端主动发起下一个长轮训请求,等待服务端响应

特性&限制


  • 1.SSE是单向的
    消息数据是从服务器到客户端,单向传递
  • 2.如果不使用HTTP/2会受到最大打开连接数的限制
    浏览器对每个域名限制的http连接数为6,这是跨标签的。HTTP/2默认值是100


客户端接受消息


浏览器EventSource实例将创建一个持久的HTTP连接,直到通过调用关闭eventSource.close()。


const es = new EventSource('/v1/index/es')
  es.onopen = () => {
    console.log('es open')
  }
  es.onerror = (err) => {
    console.log('err', err)
  }
  es.addEventListener('test', (res) => {
    const { data } = res
    console.log('来自服端消息:', data)
  })

服务端发送消息


发送事件需要使用text/event-stream类型。每个消息均以文本块形式发送,并以一对换行符结尾。


1.格式每条收到的消息都有以下字段的组合

  event 标识所描述事件类型的字符串
    如果指定了 在浏览器上将触发指定的侦听器
    addEventListener()用于侦听命名事件。
    onmessage则处理未指定事件名称的消息。

  data 消息的数据字段
  id 事件ID
  retry 尝试发送事件时要使用的重新连接时间 必须是整数,以毫秒为单位


  1. 代码

const { Readable } = require('stream')
  // 写入数据
  const send = (stream, event, data) => {
    return stream.push(`event:${event}\ndata: ${JSON.stringify(data)}\n\n`)
  }
  router.all('/es', async (ctx) => {
    // 创建流
    const reader = new Readable()
    reader._read = function (data) {
      console.log('>')
    }

    ctx.set({
      'Content-Type''text/event-stream', // 响应格式
      'Cache-Control''no-cache',
      'Connection''keep-alive'
    })

    send(reader, 'test', { data: 111 })

    ctx.body = reader
    let count = 1
    // 模拟消息发送
    const timer = setInterval(() => {
      send(reader, 'test', { data: 111, count: count++ })
    }, 3000)

    // 处理连接断开
    ctx.req.on('close', () => {
      console.log('close')
      clearInterval(timer)
      reader.destroy()
    })
  })

代码仓库

https://gitee.com/wjj0720/server-sent-events.git




点击左下角阅读原文,到 SegmentFault 思否社区 和文章作者展开更多互动和交流,扫描下方”二维码“或在“公众号后台回复“ 入群 ”即可加入我们的技术交流群,收获更多的技术文章~

- END -


浏览 17
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报