乐趣区

关于javascript:ServerSent-Events-服务端发送事件

Server-Sent Events 服务端发送事件

大多数时候,网页必须向服务器发送申请以接管新数据。服务端发送的事件,能够将音讯推送到网页

什么是 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/ser…

  • http://ottfe.cn
退出移动版