最近在学习 http ,看到 Transfer-Encoding: chunked 这个 header ,感觉和 JavaScript 中的 stream 很像,但又有些搞不明白的地方,想请教下大家。
在 http 长连接中,对于响应 body 的数据传输由两种方式:
我想问下,按理说不是只有第二种模式下的 response 才部署有 stream 接口吗?为啥使用 fetch api 请求到第一种 response 部署有 stream 接口呢?
1
3dwelcome 2023-03-31 10:39:18 +08:00
http 流是一个很宽泛的概念,你比如 jpeg 图片,传了一小半,也可以显示一部分,但他并不是 chunked 格式。
chunked 格式主要是用来,对应 ajax 里的 readyState 等于 3: processing request 的情况。 |
2
otakustay 2023-03-31 11:17:10 +08:00
content-length 知道也不代表不能流啊,比如我的长度是 30GB ,那总也得按着带宽一点一点流给你吧,流多少用多少也很正常吧,又不能一下子砸出 30GB 过来
|
3
yezheyu OP @otakustay
第一种模式,假设是长度是 30g ,传统的处理方式是根据 Content-Length 事先在内存中开辟一个 30g 的 buffer ,等数据把 buffer 填满即意味着 tcp 连接中的这个响应接收完毕,然后再把数据交给业务代码去消费 而把 Content-Length 的响应改用 stream 模式去消费,接收一块数据,就直接交给业务代码去消费,并记下数据的长度,重复这个过程并累加计算数据长度,直到累加长度等于 30g ,也就意味着 tcp 连接中这个响应接收完毕 我这样理解对吗? 所以 JavaScript 中的 stream 只是对消费方式的一种改造,而 http 中的 stream 是对数据的一种组织方式,我这样理解对吗? |
4
otakustay 2023-03-31 22:13:08 +08:00
@yezheyu #3 是的,就算有 length 也是一个流,从这个流读字节,读到 30g 的字节后停下就行了。http 层面上无论如何都是流,js 这层就是“直接用 stream”还是“stream 在原生 API 内部处理完后变成 buffer 再给你”的区别
|
5
yezheyu OP @otakustay
那我换中说法 JavaScript 中的 stream 接口只是对消费方式的一种改造,把原来那种必须把数据完全接收到 buffer ,再一次消费,改成接收一点消费一点 而在 http 中不管使用什么方式组织数据发送,都是 http 流模式,因为这是 tcp 赋予的特性。 对于 Transfer-Encoding: chunked 是才是对数据组织方式一种改造,把数据变成分块传输,并把数据长度由在 header 整体记录,改为让每个数据块自己记录 这样理解合适吗? |
6
otakustay 2023-04-04 18:28:44 +08:00
@yezheyu #5 content-length 和 chunked 是“流”的 2 种结构描述方式,你的理解没错。chunked 多浪费一点空间(每个块要存一个长度,最后还有一个长度为 0 的块),但不用提前知道整个流的长度
|
7
otakustay 2023-04-04 18:29:06 +08:00
当然涉及到 content-encoding 以后这里面还是有不少麻烦的小细节的
|