createBidirectionalStream() 创建 QUIC 内独立可靠流,各流故障隔离、无跨流保序,须显式 close/abort 释放资源,不支持 sendOrder,与 WebSocket 的全局有序管道有本质区别。

createBidirectionalStream() 创建的是 QUIC 连接内的独立可靠流,不是 WebSocket 那种全局有序通道——它不解决队头阻塞,但能隔离故障;用它传控制指令或小数据没问题,想压低延迟别指望它。
createBidirectionalStream() 的行为本质
它返回一个 WebTransportBidirectionalStream,内部是单向 readable 和 writable 流的组合,每个流在 QUIC 层保证自身有序可靠,但和其他流完全无关。第 3 个消息丢包,只卡住这个流,不影响你同时打开的另一个音频流。
- 不是“连接级重传”:丢包只触发该流内重传,不会拖慢其他流
- 没有跨流保序:两个流发的 “msg1” 和 “msg2”,接收端谁先到谁先处理
- 必须手动管理生命周期:
writer.close()或writer.abort()缺一不可,否则 QUIC 流资源不释放
典型错误:writer 写完就扔,没 close/abort
常见现象是页面长时间运行后连接变慢、新流创建失败,甚至触发浏览器 QUIC 连接数限制(Chrome 默认约 100 流)。根本原因是未关闭的 writable.getWriter() 占着流 ID 和缓冲区。
- ✅ 正确写法:
await writer.write(data); await writer.close(); - ⚠️ 危险写法:
await writer.write(data);—— 后续无任何调用,流处于“半开”状态 - ⚠️ 异常场景下漏处理:
try { ... } catch { }里没写abort(),异常后流悬空
sendOrder 参数对实际传输影响极小
createBidirectionalStream() 不接受 sendOrder;那个参数属于 WebTransportSendStream(来自 createUnidirectionalStream())。混用时容易误以为能给双向流设优先级,其实不能。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
立即学习“前端免费学习笔记(深入)”;
- 双向流的发送顺序由
writer.write()调用顺序决定,底层 QUIC 不提供跨流调度 - 真要控制优先级:改用
createUnidirectionalStream()+ 显式sendOrder,比如sendOrder: 0给心跳,sendOrder: 10给日志 - 服务端是否响应
sendOrder取决于其实现,主流 QUIC 库(如 quiche)目前仅做尽力而为,不强保障
和 WebSocket 对比时最容易忽略的一点
WebSocket 是“一个连接一个管道”,所有消息挤在一条道上排队;createBidirectionalStream() 是“一个连接 N 条并行小路”。你开了 5 个流,就得自己维护 5 套读写逻辑、5 套错误处理、5 次 close()。没有自动复用、没有统一事件总线——自由度高,复杂度也高。
如果你只是想替换 WebSocket 做聊天,别硬套这个 API;先确认服务端已支持 WebTransport,再评估是否值得为每条消息多写三行流管理代码。真正省事的低延迟路径,其实是走 transport.datagrams,哪怕它不可靠。


















