ChatGPT对话用Websocket和使用EventSource区别

        当涉及实现 GPT 打字时,开发人员通常会考虑使用两种主要的技术:Microsoft 的 fetch-event-source 库和 WebSocket。这两种技术都能够实现实时的双向通信,但它们在一些方面有着不同的特点和适用场景。下面我们来对这两种技术进行对比。

fetch-event-source

 microsoft/fetch-event-source是一个由Microsoft开发的JavaScript库,用于在浏览器中实现Fetch Event Source功能。Fetch Event Source是一种基于事件的HTTP客户端技术,用于从服务器端获取数据的推送通知。

优点:

  1. 简单易用: fetch-event-source 是一个基于 EventSource API 的库,使用起来非常简单。只需要创建一个 EventSource 实例并指定服务器端点,即可实现服务器端推送消息的接收。
  2. 基于 HTTP: fetch-event-source 底层基于 HTTP 协议,可以利用现有的 HTTP 基础设施进行通信。这意味着不需要额外的服务器端配置,也能够轻松地穿越防火墙。
  3. 适用于简单场景: 对于简单的实时通信需求,如实时聊天、通知推送等,fetch-event-source 是一个非常合适的选择。

缺点:

  1. 单向通信: fetch-event-source 只支持从服务器端向客户端的单向通信,无法实现客户端向服务器端的双向通信。
  2. 限制: 由于基于 HTTP 长连接,fetch-event-source 在某些情况下可能会受到连接超时、重连机制等限制。

        以下是一个简单的示例,演示如何使用microsoft/fetch-event-source库来实现GPT打字

import { fetchEventSource } from '@microsoft/fetch-event-source'
const ctrl = new AbortController()
const eventSource: any = fetchEventSource('https://xxx.xx.xx/gptchat/gpt', {
  method: 'POST',
  mode: 'no-cors',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    uuid: 1212,
    input: '000042776159',
    genType: '专家研究报告',
    break: 0,
  }),
  signal: ctrl.signal,
  onmessage(ev) {
    console.log(ev.data)
    eventSource.abort()
  },
  onclose() {
    eventSource.abort()
  },
  onerror(error) {
    eventSource.abort()
  },
})

        在这个示例中,我们创建了一个新的EventSource对象,并指定了要连接的服务器端点'/gpt-typing'。然后,我们监听了几种事件,包括消息事件(onmessage)、连接打开事件(onopen)、连接关闭事件(onclose)和错误事件(onerror)。当服务器端发送消息时,会触发onmessage事件,并将消息内容显示在控制台上。

        这样,我们就可以利用microsoft/fetch-event-source库来实现在浏览器中接收GPT打字的推送通知。

import { useWebSocket } from '@vueuse/core'

export interface IWebSocketConfig {
  wsUrl: string
  isHeartbeat?: boolean
  isAutoReconnect?: boolean
  immediate?: boolean
  autoReconnect?: {
    retries?: number
    delay?: number
  }
  heartbeat?: {
    message?: string
    interval?: number
    pongTimeout?: number
  }
  onFailedCall?: Function
  onConnectedCall?: Function
  onDisconnectedCall?: Function
  onErrorCall?: Function
  onMessageCall?: Function
}

export const useWebSocketHook = (options?: IWebSocketConfig): any => {
  const {
    autoReconnect = {},
    isHeartbeat = false,
    isAutoReconnect = false,
    immediate = false,
    heartbeat = {},
    onConnectedCall,
    onDisconnectedCall,
    onErrorCall,
    onMessageCall,
    onFailedCall,
    wsUrl,
  } = options ?? {}

  const { status, data, send, open, close, ws } = useWebSocket(wsUrl, {
    autoReconnect: isAutoReconnect
      ? {
          retries: 3, // 最大重试次数。
          delay: 1000, // 延迟
          onFailed() {
            console.log('*** Failed to connect WebSocket after 3 retries ***')
            onFailedCall && onFailedCall()
          },
          ...autoReconnect,
        }
      : false,
    immediate: immediate,
    heartbeat: isHeartbeat
      ? {
          message: 'ping',
          interval: 1000,
          pongTimeout: 50000,
          ...heartbeat,
        }
      : false,
    onConnected(ws: WebSocket) {
      onConnectedCall && onConnectedCall(ws)
    },
    onDisconnected(ws: WebSocket, event: CloseEvent) {
      onDisconnectedCall && onDisconnectedCall(ws, event)
    },
    onError(ws: WebSocket, event: Event) {
      onErrorCall && onErrorCall(ws, event)
    },
    onMessage(ws: WebSocket, event: MessageEvent) {
      onMessageCall && onMessageCall(ws, event)
    },
  })

  return {
    status,
    data,
    send,
    open,
    close,
    ws,
  }
}
import { useWebSocketHook } from '@/hooks/useWebSocket'

const { send, open, close, data, status } = useWebSocketHook({
  isAutoReconnect: true,
  wsUrl: import.meta.env.VITE_SOCKET_URL,
  onConnectedCall: (ws: WebSocket) => {
    console.log('连接成功!', ws, status)
    state.wsReadyState = ws.readyState
    if (state.isSendData) {
      handleSendData()
    }
  },
  onMessageCall: () => {
    handleReceivedData(data.value)
  },
  onDisconnectedCall: (ws: WebSocket) => {
    console.log('断开连接!', ws)
    state.wsReadyState = ws.readyState
  },
  onErrorCall: (ws: WebSocket) => {
    console.log('连接失败!', ws.readyState)
    state.wsReadyState = ws.readyState
  },
  onFailedCall: () => {
    state.wsReadyState = -1
    state.isLoading = false
    state.generateLoading = false
  },
})

WebSocket

优点:

  1. 双向通信: WebSocket 支持全双工通信,客户端和服务器端都可以随时发送消息,实现实时的双向通信。
  2. 低延迟: WebSocket 使用 TCP 协议,相比 HTTP 长连接具有更低的延迟和更高的效率,适合实时性要求较高的场景。
  3. 灵活性: WebSocket 提供了更灵活的消息传输方式,可以发送文本、二进制数据等多种类型的消息。

缺点:

  1. 复杂度: 相对于 fetch-event-source,WebSocket 的使用稍显复杂,需要处理连接管理、心跳检测等细节。
  2. 部署限制: WebSocket 通常需要额外的服务器端配置和支持,某些环境下可能存在部署限制。

对比总结

  • 适用场景: 对于简单的实时通信需求,如消息通知、事件推送等,fetch-event-source 是一个简单、轻量级的选择;而对于需要实现双向通信、低延迟等要求较高的场景,则应选择 WebSocket。
  • 复杂度: fetch-event-source 更简单易用,适合于快速实现简单的实时通信功能;WebSocket 虽然稍显复杂,但提供了更多灵活性和功能扩展的可能性。
  • 性能和效率: WebSocket 相比 fetch-event-source 在延迟和效率上更有优势,特别是在需要大量实时数据传输的场景下,WebSocket 更能满足需求。

综上所述,开发人员应根据具体的需求和场景选择合适的技术来实现 GPT 打字功能。如果是简单的实时通信需求,fetch-event-source 可能更适合;而对于更复杂、性能要求更高的场景,则应选择 WebSocket。

  • 33
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值