关于server-sent events和fetch请求返回的ReadableStream对象
来源:3-14 对话支持流式响应-前端解析二进制流

zxcads
2023-06-05
我在opnai的文档中看到对stream: true的描述
stream: true
If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only server-sent events as they become available, with the stream terminated by a data: [DONE] message. Example Python code.
这里使用了server-sent events
,我查看了server-sent events
的MDN文档,文档对server-sent events的使用说明是这样的,但是在课程的代码中没有看到类似的处理。
// 处理server-sent events
const evtSource = new EventSource(url)
evtSource.addEventlisenter('event', callback)
但是我不明白使用fetch请求的body是如何接收server-sent events的,我知道Response.body本身就是一个ReadableStream对象,例如下面这段代码:
fetch('https://www.example.org')
.then((response) => response.body)
.then((rb) => {
const reader = rb.getReader();
return new ReadableStream({
start(controller) {
// The following function handles each data chunk
function push() {
// "done" is a Boolean and value a "Uint8Array"
reader.read().then(({ done, value }) => {
// If there is no more data to read
if (done) {
console.log('done', done);
controller.close();
return;
}
// Get the data and send it to the browser via the controller
controller.enqueue(value);
// Check chunks by logging to the console
console.log(done, value);
push();
});
}
push();
},
});
})
.then((stream) =>
// Respond with our stream
new Response(stream, { headers: { 'Content-Type': 'text/html' } }).text()
)
.then((result) => {
// Do things with result
console.log(result);
});
流式解析好像和server-sent events本身并没有关系,就算没有server-sent events也依然可以流式解析响应,我理解的对吗?请老师解惑。
1回答
-
很好的问题。
要回答这个问题首先需要明确 fetch 可以请求 event-source,只是因为没有 onmessage 方法导致无法处理流数据,但请求可以拿到相应的数据流,课程中通过 ReadableStream 搭配 fetch 去实现流式解析。业内也有比较完善的最佳实践,参见 @microsoft/fetch-event-source。
为什么不使用 EventSource ?
参见上文的 @microsoft/fetch-event-source 中举出点:
不能在请求正文中传递信息:必须将执行请求所需的所有信息编码到 URL 中,大多数浏览器的 URL 长度限制为 2000 个字符。
无法传递自定义请求标头。
只能进行 GET 请求 - 没有办法指定其他方法。
如果连接被切断,则无法控制重试策略:浏览器会默默地为您重试几次,然后停止,这对于任何稳健型应用程序都不够好。
012023-06-06
相似问题