🌐 Streams

流是 QUIC 中主要的数据承载抽象。一旦会话建立,流可以由本地端点或远程端点发起。

🌐 Streams are the primary data-carrying abstraction in QUIC. A stream can be initiated by either the local endpoint or the remote peer once a session is established.

流可以是双向的(数据在两个方向流动)或单向的(数据仅在一个方向流动)。quic 模块提供了用于创建每种类型的独立 API:session.createBidirectionalStream()session.createUnidirectionalStream()。由远程对等方启动的流通过 session.onstream 回调传递。

🌐 Streams can be either bidirectional (data flows in both directions) or unidirectional (data flows in only one direction). The quic module provides separate APIs for creating each kind: session.createBidirectionalStream() and session.createUnidirectionalStream(). Streams initiated by a remote peer are delivered via the session.onstream callback.

有两种方式可以将数据写入流:

🌐 There are two ways to write data to a stream:

  • 主体来源 — 在创建流时传入 body 选项(或调用 stream.setBody())。主体可以是字符串、ArrayBufferArrayBufferViewBlobFileHandleAsyncIterable、同步的 Iterable,或解析为这些任意类型的 Promise。一个 null 主体会立即关闭可写端。当数据已经可用或可以表示为可迭代对象时,这是最简单的方法。
  • 写入器 — 访问 stream.writer 以增量推送数据。写入器提供同步方法(writeSync()writevSync()endSync()),这些方法会立即返回,以及异步等效方法(write()writev()end()),在遇到背压时会等待缓冲区排空。writeSync() 在写入缓冲区已满时返回 false;调用者应在重试前等待缓冲区排空。

对于给定的流,这两种方法是互斥的。

🌐 These two approaches are mutually exclusive for a given stream.

读取是通过将流作为异步可迭代对象进行迭代来完成的。每次迭代都会产生一批 Uint8Array 块:

🌐 Reading is done by iterating the stream as an async iterable. Each iteration yields a batch of Uint8Array chunks:

for await (const chunks of stream) {
  for (const chunk of chunks) {
    // Process each Uint8Array chunk
  }
} 

每个流只能获取一个异步迭代器。该流也兼容 node:stream/iter 工具,例如 Stream.bytes()Stream.text()Stream.pipeTo()

🌐 Only one async iterator can be obtained per stream. The stream is also compatible with node:stream/iter utilities such as Stream.bytes(), Stream.text(), and Stream.pipeTo().