1前言

​ 目前JS实时通信方式主要由:websocket、socket.io、eventSource(SSE)这三种方式。有人就也许好奇有了websocket这种实时通信方式,为啥还需要eventSource呢?这是因为不同客户端场景,有着各自的优势。

​ eventSource是单向通信,而websocket是双向通信。在新闻推送、股票行情这种只需要服务器发送消息给客户端场景,使用SSE更加合适,另外SSE是使用HTTP传输的。而websocket要求全双工连接和一个新的websocket服务器去处理,

​ 因为各有所长,我们只需要根据实际应用场景,去选择最优的应用方案。

2介绍

​ EventSource 对象接口用于接收服务器发送的事件。它通过 HTTP 连接到服务器,已 text/event-stream 格式接收事件,不关闭连接。

​ EventSource 对象主要用于 Server-Sent Events(简称 SSE)的技术。这是一种能让浏览器通过 HTTP 连接自动收到服务器端更新的技术。

​ 这个技术的作用是可以完成从服务器端到客户端(浏览器)单向的消息传递。因此我们可以用这个来做推送。

​ 相关文档:https://developer.mozilla.org/zh-CN/docs/Web/API/EventSource

2.1浏览器兼容性

img

2.2构造函数

const eventSource = new EventSource()

2.3属性

说明 属性
onerror 当发生错误时被调用,并且在此对象上派发 error 事件
onmessage 服务器端发送给客户端一条消息时触发
onopen SSE 连接刚打开时触发
readyState 表示连接状态(CONNECTINGOPENCLOSED
url 代表源头的 URL

2.4方法

方法 说明
close 关闭连接

2.5通信过程

在浏览器通信截图:

2.6服务端

服务端返回响应头必须包含以下header:

Content-Type: text/event-steam 
Cache-Control: no-cache
Connection: keep-alive

服务器返回的数据格式为文本型,由若干个message组成,每个message用\n\n分割

每个message内容是[key]:value

key有四种情况:id、event(type)、data、tetry

  • id 为每个返回数据的唯一标识,浏览器用lastEventId读取id,一旦连接断开,浏览器会从新发送http请求,带有特殊请求头Last-Event-Id,代表断开时的id,用于建立重新连接,属于一种重连的同步机制.

  • data 数据内容一般放于data字段。

  • event(type):消息类型,一般默认为message,服务端可以自定义,前端用addEventListener()监听。

  • retry:代表服务器重新发送请求的间隔时间。

3实例运用

3.1原生EventSource

  /*
  * new EventSource(url, configuration)
  * url:请求地址路径
  * configuration 可选项:withCredentials,默认为false,指是否CORS设置
  *
  */
  const eventSource = new EventSource('/api/stream');
  // 正常的EventSource,我们只关心以下三个事件
  /*
  * open:订阅成功(和后端连接成功)
  */
  eventSource.addEventListener("open", function(e) {
    console.log('open successfully')
  })
  /*
  * message:后端返回信息,格式可以和后端协商
  */
  eventSource.addEventListener("message", function(e) {
    console.log(e.data)
  })
  /*
  * error:错误(可能是断开,可能是后端返回的信息)
  */
  eventSource.addEventListener("error", function(err) {
    console.log(err)
    // 类似的返回信息验证,这里是实例
    err && err.status === 401 && console.log('not authorized')
  })
  
  // 需要关闭了
  eventSource.close()

注意:因为原生EventSource无法进行自定义配置,例如header、method等,因此我们需要引用其他的封装库

3.2fetch-event-source

使用post的方式请求eventSource

安装依赖:npm install --save @rangermauve/fetch-event-source

import { fetchEventSource } from '@microsoft/fetch-event-source'

fetchEventSource('/api/stream', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(dataJson),
        onopen() {},
        onmessage(event) {
          const jsonData = JSON.parse(event.data)
          let respondTexts = jsonData.delta
          let finishStatus = jsonData.finished
        },
        onerror() {},
        onclose() {}
      })
posted on 2023-08-08 20:06  仰望IT星空  阅读(4449)  评论(0编辑  收藏  举报