EventSource 引发的一系列事件

这篇具有很好参考价值的文章主要介绍了EventSource 引发的一系列事件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

大家好,我是江辰,最近小小的实现了下 chatGPT 的问答式回复,调研了前端如何实现这种问答式请求,有几种方案,Http、EventSource、WebSocket,三种实现方案各有优缺点,Http 和 WebSocket ,想必大家耳闻能详,这里我讲讲 EventSource

EventSource

EventSource 是服务器推送的一个网络事件接口。一个 EventSource 实例会对 HTTP 服务开启一个持久化的连接,以text/event-stream 格式发送事件,会一直保持开启直到被要求关闭。

一旦连接开启,来自服务端传入的消息会以事件的形式分发至你代码中。如果接收消息中有一个事件字段,触发的事件与事件字段的值相同。如果没有事件字段存在,则将触发通用事件。

与 WebSockets,不同的是,服务端推送是单向的。数据信息被单向从服务端到客户端分发。当不需要以消息形式将数据从客户端发送到服务器时,这使它们成为绝佳的选择。例如,对于处理社交媒体状态更新,新闻提要或将数据传递到客户端存储机制(如 IndexedDB 或 Web 存储)之类的,EventSource 无疑是一个有效方案。

— 引自 MDN

对比 WebSocket,它就是简单,方便,在特定的一些场景下,比如聊天消息或市场价格,这就是 EventSource 擅长的

使用方式

它的使用方式极其简单

const evtSource = new EventSource('sse.php');
const eventList = document.querySelector('ul');

evtSource.onmessage = function(e) {
 let newElement = document.createElement("li");

  newElement.textContent = "message: " + e.data;
  eventList.appendChild(newElement);
}

对吧,几行代码搞定,如何携带参数,在 new EventSource('sse.php?id=123'); 其中 id=123,就是我们要给链接传的参数

问题来了

EventSource 引发的一系列事件,前端

当我实现之后,发现它在不断的自动重连?搜了很多文档,想不通,为何会自动重连,这里伏笔。想不通,ok,我就换个思路,改用 Axios 实现

axios

axios 实现如下

const streamToString = async (readableStream) => {
  return new Promise((resolve, reject) => {
    const chunks = [];
    readableStream.on("data", (data) => {
      chunks.push(data);
    });
    readableStream.on("end", () => {
      resolve(Buffer.concat(chunks).toString('base64'))
    });
    readableStream.on("error", reject);
  });
}


axios({
  method: 'get',
  url:`//xxx/api/chat/stream?prompt=${textarea.current.value.trim()}`,
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  responseType: 'stream'
}).then(async res => {
  const raw = await streamToString(res.data);
})

此时还不知问题的**严重性!**实现完之后,发现不对劲啊,readableStream.on is not a fucntion,???(黑人问号脸),遂打印 log 看看输出的 res.data 是啥,字符串?根本不是一个方法啊,但看网上实现,是这样啊,没错?又看了几遍,都是这样实现的,很懵,直到看了下 axios 的 issue,传送门,2016年就有人提出了这个问题,也就是说 axios 在浏览器侧一直没有实现 steram,我内心cnm,网上的文档都是假的!!!

也就是说,按照目前MDN说法,responseType 支持的类型有,arraybuffer、blob、document、json、text、ms-stream,其中 ms-stream,此响应类型仅允许用于下载请求,并且仅受 Internet Explorer 支持

坑坑坑,又要开始了其他方案,想想 Fetch 能不能行,浏览器原生支持哦!

Fetch

Fetch API 提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应。它还提供了一个全局 fetch() 方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。

这种功能以前是使用 XMLHttpRequest 实现的。Fetch 提供了一个更理想的替代方案,可以很容易地被其他技术使用,例如 Service Workers。Fetch 还提供了专门的逻辑空间来定义其他与 HTTP 相关的概念,例如 CORS 和 HTTP 的扩展。

— 引自 MDN

利用 Fetch 实现了如下代码

const response = await fetch(`//xxx/api/chat/stream?prompt=${textarea.current.value.trim()}`);
const reader = response.body.getReader();

const eventList = document.querySelector('ul');
while (true) {
  const { value, done } = await reader.read();
  const utf8Decoder = new TextDecoder('utf-8');
  let data: any = value ? utf8Decoder.decode(value, {stream: true}) : '';
  try {
    data = JSON.parse(data)
    if (data.id || !data.content) {
      return
    }

    let newElement = document.createElement("li");
    newElement.textContent = "message: " + data.content;
    eventList.appendChild(newElement);
  } catch (e) {
  }
  if (done) {
    break;
  }
}

实现没有问题,在我电脑上也跑通了,能稳定接收服务端消息,不会自动重连,万事大吉,转交朋友试用
。。。。

交给朋友试用,反馈说,会出现回复不全???,调试搞起

浏览器侧接收的消息
EventSource 引发的一系列事件,前端

抓包看的消息
EventSource 引发的一系列事件,前端

对比看,浏览器侧**丢包!丢包了!!!**几番排查下来,不知为何会丢包,而且是只有 Windows 上会丢包(必现),macOS 上不会,不懂了呀,我们自己测试 Win 下 ping 都是稳定的,有懂的同学,可以告知下,谢谢!

最终解决方案

又回到 EventSource,没错,又回来了,折腾下来发现,每次收完消息,你必须手动关闭下,evtSource.close();,才不会自动重连,而且自动重连就是 EventSource 的特性之一,害,伏笔解决了。这个关闭有个前提是,服务端下发字段告诉你,能关闭,你才能关闭哦,折腾啊!!!

总结

通过这次的学习,让我对 EventSource 以及 Fetch、Axios 有了一次深刻的认知,大家看完觉得还不错的话,欢迎点赞,收藏哦
文章同步更新平台:掘金、CSDN、知乎、思否、博客,公众号(野生程序猿江辰)

我的联系方式,v:Jiang9684,欢迎和我一起学习交流

本文由mdnice多平台发布文章来源地址https://www.toymoban.com/news/detail-692081.html

到了这里,关于EventSource 引发的一系列事件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 网络安全领域关键信息泄露事件引发关注

    近日,一家知名网络安全公司发布了一份报告揭露了一起重大信息泄露事件。据称,该事件涉及大量敏感用户数据的泄露引发了全球网络安全领域的广泛关注。 根据报道,该事件发生在全球范围内涉及多个国家和组织。专家指出,此次泄露事件的规模和影响力令人震惊突显了

    2024年02月09日
    浏览(36)
  • 服务器给前端实时推送数据轻量化解决方案eventSource+Springboot

    body代码 js代码 WebFlux 框架依赖jar包 控制器代码 Flux.interval(Duration.ZERO,Duration.ofSeconds(1)),等待0秒开始,间隔1秒,Flux流数据里面的数字加1 三、效果展示 时间和数字一直在增加,后端在不断推送,前端订阅到数据更新到页面 相对于websocket简单很多,只需要很少的代码就实现前

    2024年04月11日
    浏览(44)
  • 数据隐私保护:网站文章采集txt事件引发的用户隐私安全风险

    近期,以“网站文章采集txt”为名义的企业因涉嫌非法收集用户数据而掀起一阵公众争议。该事件再度聚焦于数据隐私保护的议题。接下来,本文将深度剖析这一问题的实质。 1.采集行为遭到质疑 据悉,网站文章采集txt公司因涉嫌非法获取用户信息及进行商业利用而遭受指控

    2024年04月08日
    浏览(49)
  • Cocos Creator3.8 项目实战(二)cocos creator编辑器中绑定事件引发的bug解决

    问题描述: 编辑器里面多个按钮绑定同一个脚本,并配置事件,脚本中有其他消息监听,引起逻辑混乱。 问题原因: 编辑器里面多个按钮绑定同一个脚本, 每次绑定一个按钮事件,就会导致加载一次脚本 ,如上绑定了多个按钮的事件,脚本也就被加载多次,导致初始化接

    2024年02月07日
    浏览(52)
  • 浏览器缓存引发的odoo前端报错

    前两天,跑了一个odoo16项目,莫名其妙的前端报错, moment.js 报的错, 这是一个时间库,不是我自己写的代码,我也没做过任何修改,搞不清楚为什么报错。以为是odoo的bug,所以从gitee下载了odoo16最新的代码,测试了一下还是报错。 后来换成了一个非常老的odoo16版本,这回不

    2024年02月02日
    浏览(51)
  • [pyqt5]动态加载ui文件并给菜单的一个子菜单添加触发事件

    场景:大家都知道如果直接将ui文件转成py文件后,如果产品经理要你加一些界面控件,你就得改转换后代码这样很麻烦,我们可以直接加载ui文件,然后编写触发事件,因此写了一个简单案例,证明切实可行,首先我们设计一个简单界面,就是加一个菜单-writer就可以了  然后

    2024年02月12日
    浏览(56)
  • 和前端吵架的一天

    前段时间在开发公司的积分商城,前期都没啥问题,一切都很顺利,到了跟前端联调的时候,尴尬了,吵起来了,搞得我很不爽,具体原因如下: 大致原因是:他说 get 请求携带body他那里处理不了,我就很奇怪了,为什么试配不了,当时很无语,一口咬定就觉得是他的问题,

    2023年04月08日
    浏览(44)
  • 关于括号的一系列问题

    对于只出现一种括号的字符串,看这个字符串中的括号是否匹配 以及 匹配的个数: 一般来说有两种匹配方式: 例如: (()()()) 第一种匹配是此字符串有4组括号对匹配完成 第二种匹配是此字符串有3组括号对匹配完成 对于第一种匹配方式:有两种选择:栈或者直接

    2024年02月11日
    浏览(27)
  • 安装fasttext的一系列问题(全)

    环境配置:windows10+python3.10 前言:Gensim中的fasttext不能做文本分类,对于想学习fasttext进行文本分类、情感分析的同学还是必须下载Facebook的fasttext 在该python libs (或者粘贴该链接https://www.lfd.uci.edu/~gohlke/pythonlibs/#fasttext)搜索fasttext 下载whl文件,文件名: fasttext-0.9.2-cp310-cp31

    2024年02月06日
    浏览(57)
  • RabbitMQ启动失败的一系列尝试

    在三台 CentOS 7.x上部署了RabbitMQ集群,如下:  服务器IP hostname 节点说明 端口 管控台地址 192.168.31.101 master rabbitmq master 5672 http://192.168.11.71:15672 192.168.31.102 slave1 rabbitmq slave 5672 http://192.168.11.72:15672 192.168.31.103 slave2 rabbitmq slave 5672 http://192.168.11.73:15672 集群部署教程可参考:Rabb

    2024年02月04日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包