跳到正文

请求竞态与实时通信 ​

  • 状态:未准备
  • 适用方向:前端 / Go 全栈
  • 最近复习:待填写
  • 下次复习:待安排

一句话回答 ​

异步结果应按会话、请求和业务版本判断是否仍有效,不能只按到达顺序覆盖状态;实时连接还需明确传输保证、业务确认、恢复策略和资源生命周期。

原理解释 ​

搜索请求为什么会显示旧结果? ​

用户先搜 A 再搜 B,A 的响应可能更晚到达。防抖只减少请求,不保证已发请求的返回顺序。可以取消前次请求,并用请求序号或有效标志拒绝过期结果;取消不等于服务端业务操作已撤销。

js
let version = 0
async function search(query) {
  const current = ++version
  try {
    const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`)
    if (!response.ok) throw new Error(`HTTP ${response.status}`)
    const data = await response.json()
    if (current === version) renderResults(data)
  } catch (error) {
    if (current === version) renderError(error)
  }
}
// renderResults/renderError 为页面提供的回调。

轮询、SSE、WebSocket ​

  • 轮询:兼容和实现简单,但存在重复请求与更新延迟。
  • SSE:服务端到客户端的事件流,原生 EventSource 具有重连机制,但鉴权头等使用限制需考虑。
  • WebSocket:双向消息通道,适合聊天、信令;浏览器原生 API 不自动实现应用级重连、重放或业务 ACK。

同一 WebSocket 连接内有传输顺序保证,不代表多个连接、多个异步处理链和多个引擎的业务结果具有统一顺序。断线后是否补齐、重发是否去重,都要应用协议定义。

场景与边界 ​

心跳用于发现连接或对端状态异常,不能证明消息业务处理完成。重连通常需要退避、抖动、上限和鉴权重新确认;本地发送成功不代表服务端已落库。长时间高频消息还需观察 bufferedAmount、队列长度与内存,浏览器 WebSocket API 不提供自动背压控制。

项目中的应用 ​

  • SimulSpeak:按句子身份和阶段合并字幕,不让迟到 partial 覆盖已确认状态;具体受保护分支需沿测试确认。
  • EinoTalk:区分本地乐观消息和服务端回显,避免重复追加。
  • 自动重连、离线补偿和完整业务 ACK 是复习扩展,不能据此认定项目已经实现。

常见追问 ​

  • 如何避免重复消息? 使用稳定业务 ID 去重,规定临时 ID 与服务端 ID 如何对账,并保留必要状态。
  • 如何验证竞态? 人工控制两个请求或事件的完成顺序,覆盖旧请求晚到、切会话、卸载和重复回显。
  • WebRTC 与 WebSocket 什么关系? WebSocket 可承载信令,WebRTC 用于媒体或数据通道,两者职责不同。

参考资料 ​

理解机制,讲清取舍,用复盘检验掌握。