关于 JavaScript 中 stream 的一些疑惑

2023-03-31 10:24:34 +08:00
 yezheyu

最近在学习 http ,看到 Transfer-Encoding: chunked 这个 header ,感觉和 JavaScript 中的 stream 很像,但又有些搞不明白的地方,想请教下大家。

在 http 长连接中,对于响应 body 的数据传输由两种方式:

我想问下,按理说不是只有第二种模式下的 response 才部署有 stream 接口吗?为啥使用 fetch api 请求到第一种 response 部署有 stream 接口呢?

1667 次点击
所在节点    程序员
8 条回复
3dwelcome
2023-03-31 10:39:18 +08:00
http 流是一个很宽泛的概念,你比如 jpeg 图片,传了一小半,也可以显示一部分,但他并不是 chunked 格式。

chunked 格式主要是用来,对应 ajax 里的 readyState 等于 3: processing request 的情况。
otakustay
2023-03-31 11:17:10 +08:00
content-length 知道也不代表不能流啊,比如我的长度是 30GB ,那总也得按着带宽一点一点流给你吧,流多少用多少也很正常吧,又不能一下子砸出 30GB 过来
yezheyu
2023-03-31 13:59:31 +08:00
@otakustay
第一种模式,假设是长度是 30g ,传统的处理方式是根据 Content-Length 事先在内存中开辟一个 30g 的 buffer ,等数据把 buffer 填满即意味着 tcp 连接中的这个响应接收完毕,然后再把数据交给业务代码去消费

而把 Content-Length 的响应改用 stream 模式去消费,接收一块数据,就直接交给业务代码去消费,并记下数据的长度,重复这个过程并累加计算数据长度,直到累加长度等于 30g ,也就意味着 tcp 连接中这个响应接收完毕

我这样理解对吗?

所以 JavaScript 中的 stream 只是对消费方式的一种改造,而 http 中的 stream 是对数据的一种组织方式,我这样理解对吗?
otakustay
2023-03-31 22:13:08 +08:00
@yezheyu #3 是的,就算有 length 也是一个流,从这个流读字节,读到 30g 的字节后停下就行了。http 层面上无论如何都是流,js 这层就是“直接用 stream”还是“stream 在原生 API 内部处理完后变成 buffer 再给你”的区别
yezheyu
2023-04-04 17:52:28 +08:00
@otakustay

那我换中说法

JavaScript 中的 stream 接口只是对消费方式的一种改造,把原来那种必须把数据完全接收到 buffer ,再一次消费,改成接收一点消费一点

而在 http 中不管使用什么方式组织数据发送,都是 http 流模式,因为这是 tcp 赋予的特性。

对于 Transfer-Encoding: chunked 是才是对数据组织方式一种改造,把数据变成分块传输,并把数据长度由在 header 整体记录,改为让每个数据块自己记录

这样理解合适吗?
otakustay
2023-04-04 18:28:44 +08:00
@yezheyu #5 content-length 和 chunked 是“流”的 2 种结构描述方式,你的理解没错。chunked 多浪费一点空间(每个块要存一个长度,最后还有一个长度为 0 的块),但不用提前知道整个流的长度
otakustay
2023-04-04 18:29:06 +08:00
当然涉及到 content-encoding 以后这里面还是有不少麻烦的小细节的
yezheyu
2023-04-05 12:54:34 +08:00
@otakustay 好的,多谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/928691

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX