一文解析ChatGPT 之 Fetch 请求
作者:川、
SSE 介绍
随着 ChatGPT 已生活工作中的一部分,介绍其中一种服务器端推送技术——Server-Sent Events (SSE),并简单实现其效果。
SSE 是一种 HTML5 技术,它允许服务器向客户端发送事件,从而实现服务器端推送。相对于 WebSockets 或长轮询技术,SSE 提供了更简单的方式来实现服务器端推送,并且支持更广泛的客户端和服务器端。
在 SSE 中,客户端通过向服务器端发送一个 HTTP 请求,请求某个资源,并且指定响应的类型是"text/event-stream"。服务器端在响应请求时,将数据格式化为事件流的形式,并通过 HTTP 响应发送回客户端。客户端通过事件流中的数据,可以实现实时地更新 UI 等操作。
下面是一个 SSE 的 Demo,展示了如何通过 SSE 实现一个简单的服务器端推送应用。
服务端代码:
const express = require('express'); const app = express(); const port = 3600; app.get('/stream', (req, res) => { const { message = '' } = req.query // 3个请求头重点,需要返回text/event-stream,告知浏览器以何种类型解析 res.set({ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', }); let step = 0; // 定时器依次返回message const time = setInterval(() => { const data = { message: message[step++]}; // 每个消息以 \n\n分割 res.write(`data: ${JSON.stringify(data)}\n\n`); if (step > message.length - 1) { res.end() clearInterval(time) } }, 500); }); app.listen(port, () => console.log(`Server running at http://localhost:${port}`));
客户端代码:
// 创建一个EventSource const eventSource = new EventSource(`/stream?message=${message}`); // 监听服务器返回的数据 eventSource.onmessage = function (event) { console.log(event.data); }; eventSource.onerror = function () { eventSource.close(); };
在上面的代码中,我们通过 EventSource
对象创建了一个 SSE 连接,并指定了服务器端的 URL。当有事件流数据时,onmessage
回调函数会被调用。 network 中可看到一条类型为eventsource
的请求,其以下内容
咋和 ChatGPT 控制台看到的内容不一样?🙄
ChatGPT 回车后,并未发送eventsource
请求,而是发送了一个 fetch 请求,原因又是什么呢,仔细看
观察上图可得它发送了一个 fetch 的 POST 请求,服务端响应的是一个eventsource
,那么 fetch 又能如何实现eventsource
响应呢?因为 fetch 并没有onmessage
方法~
通过一番查找学习~主要有两个关键的 API
fetch用于发起SSE请求,而EventSource用于处理服务器端推送的数据。结合两个API简单实现一个fetchStream
方法
const fetchStream = (url, params) => { const { onmessage, onclose, ...otherParams } = params; const push = async (controller, reader) => { const { value, done } = await reader.read(); if (done) { controller.close(); onclose?.(); } else { onmessage?.(Uint8ArrayToString(value)); controller.enqueue(value); push(controller, reader); } }; // 发送请求 return fetch(url, otherParams) .then((response) => { // 以ReadableStream解析数据 const reader = response.body.getReader(); const stream = new ReadableStream({ start(controller) { push(controller, reader); }, }); return stream; }) .then((stream) => new Response(stream, { headers: { 'Content-Type': 'text/html' } }).text()); };
调用方法
fetchStream(`/stream?message=${message}`, { method: 'GET', headers: { 'accept': 'text/event-stream', 'Content-Type': 'application/json', }, onmessage: (res) => { // todo console.log(res); }, });
经过简单封装实现ChatGPT的应答请求效果~
另外推荐一个成熟的第三方依赖fetch-event-source
点击查看
Server-Sent Events 相对于其他技术的优缺点
与WebSockets相比,SSE技术的优点在于:
- 更简单的实现:SSE技术使用标准的HTTP协议来发送和接收数据,因此不需要额外的握手和协议协商步骤。这使得SSE技术的实现更加简单,尤其是对于服务器端。
- 更广泛的兼容性:SSE技术使用标准的HTTP协议,因此可以被大多数Web浏览器和服务器端支持。相比之下,WebSockets需要浏览器和服务器端都支持WebSocket协议。
- 更少的网络开销:SSE技术使用HTTP长连接来实现服务器端推送,因此相比WebSockets需要更少的网络开销和资源消耗。
与长轮询技术相比,SSE技术的优点在于:
- 实时性更好:SSE技术可以实时地向客户端推送数据,因此可以实现更快的响应速度和更好的实时性。
- 更少的网络开销:SSE技术使用HTTP长连接来实现服务器端推送,因此相比长轮询需要更少的网络开销和资源消耗。
- 更好的客户端兼容性:SSE技术可以被大多数现代浏览器和设备支持,因此更容易实现客户端兼容性。
总结
最后呈上一个完整的demo,github地址
以上就是一文解析ChatGPT 之 Fetch 请求的详细内容,更多关于ChatGPT Fetch 请求的资料请关注脚本之家其它相关文章!