首页 > Ai资讯 > Ai知识库 > 实现聊天机器人打字机形式输出内容:SSE原理介绍及Post实现方式

实现聊天机器人打字机形式输出内容:SSE原理介绍及Post实现方式

发布时间:2024年06月06日

一.SSE原理介绍

1、SSE基础概念

SSE(Server Sent Event),直译为服务器发送事件,顾名思义,也就是客户端可以获取到服务器发送的事件。我们常见的 http 交互方式是客户端发起请求,服务端响应,然后一次请求完毕;但是在 sse 的场景下,客户端发起请求,连接一直保持,服务端有数据就可以返回数据给客户端,这个返回可以是多次间隔的方式

2、SSE特点

  • 长连接

  • 服务端可以向客户端推送信息

从 sse 的特点出发,我们可以大致的判断出它的应用场景,需要轮询获取服务端最新数据的 case 下,多半是可以用它的。比如显示当前网站在线的实时人数,法币汇率显示当前实时汇率,电商大促的实时成交额等等

3、SSE使用场景

在web端消息推送功能中,由于传统的HTTP协议是由客户端主动发起请求,服务端才会响应。基本的ajax轮询技术便是如此。而在SSE中,浏览发送一个请求给服务端,通过响应头中的Content-Type:text/event-stream等向客户端声名这是一个长连接,发送的是流数据,这样客户端就不会关闭连接,一直等待服务端发送数据。

如果服务器返回的数据中包含了事件标识符,浏览器会记录最后一次接收的事件的标识符。如果与服务器的连接中断,当浏览器再次进行连接时,会通过头来声明最后一次接收的事件的标识符。服务器端可以通过浏览器发送的事件标识符来确定从哪个事件来继续连接

4、SSE注意事项

保证数据的完整性 :客户端在每次接收到消息时,会把消息的id 字段作为内部属性 Last-Event-ID储存起来。SSE默认支持断线重连机制,在连接断开时会 触发EventSource的error事件,同时自动重连。再次连接成功时 EventSource会把Last-Event-ID属性作为请求头发送给服务器,这样服务器就可以根据这个Last-Event-ID作出相应的处理。这里需要注意⚠️的是,id字段不是必须的,服务器有可能不会在消息中带上id字段,这样子客户端就不会存在Last-Event-ID这个属性。所以为了保证数据可靠,我们需要在每条消息上带上id字段。

SSE不支持IE浏览器

5、实战

1.get方式实现 

前端

      if(window.EventSource){
        // 根据环境的不同,变更url
        const url = config.host2;
   
      var that=this;
      this.eventSource=new EventSource(`${url}/see`,{msg:this.curMessage});

        this.eventSource.onmessage = (e) => {
          const message = JSON.parse(e.data);
          //this.messages.push(message);
          console.log("已接受到消息:", e.data)
        };
        this.eventSource.onerror = (event) => {
           that.eventSource.close();
        };
        //处理服务器响应报文中的自定义事件
        this.eventSource.addEventListener("close", function (e) {
           that.eventSource.close();
        });

      } else {
        console.log("你的浏览器不支持SSE~")
      }

  后端

   [HttpGet("sse")]
        public async Task<IActionResult> GetChatResponseSSE(string message)
        {
            var response = await _chatGPTService.GetChatResponse(message);

            Response.Headers.Add("Cache-Control", "no-cache");
            Response.Headers.Add("Content-Type", "text/event-stream");

            await Response.StartAsync();

            var lines = response.Split('\n');

            foreach (var line in lines)
            {
                if (string.IsNullOrEmpty(line))
                {
                    await Response.WriteAsync("\n");
                }
                else
                {
                    await Response.WriteAsync($"data: {line}\n\n");
                    await Response.Body.FlushAsync();
                }
            }

            return new EmptyResult();
        }

2.post实现

sse本身是不支持post的方式,可以通过fetch的方式完成post相关操作。具体可以使用开源组件完成需求:https://github.com/Azure/fetch-event-source

  前端

 
     const controller = new AbortController()
      const signal = controller.signal

  fetchEventSource(`${url}`, { method:
'POST', signal: signal, headers: { 'Content-Type': 'application/json', token: window.sessionStorage.getItem('token'), }, body:JSON.stringify(message), onmessage(msg) { if(msg.event === ''){ var result= JSON.parse(msg.data); } else if (msg.event === 'close') { controller.abort(); } }, onerror(err) { throw err; //必须throw才能停止 } });

  后端

   [HttpGet("sse")]
        public async Task<IActionResult> GetChatResponseSSE(string message)
        {
            var response = await _chatGPTService.GetChatResponse(message);

            Response.Headers.Add("Cache-Control", "no-cache");
            Response.Headers.Add("Content-Type", "text/event-stream");

            await Response.StartAsync();

            var lines = response.Split('\n');

            foreach (var line in lines)
            {
                if (string.IsNullOrEmpty(line))
                {
                    await Response.WriteAsync("\n");
                }
                else
                {
                    await Response.WriteAsync($"data: {line}\n\n");
                    await Response.Body.FlushAsync();
                }
            }

            return new EmptyResult();
        }

 

如果你想要了解关于智能工具类的内容,可以查看 智汇宝库,这是一个提供智能工具的网站。
在这你可以找到各种智能工具的相关信息,了解智能工具的用法以及最新动态。