eventsourceresponse必须配合异步生成器,因sse要求服务端提供asyncgenerator以维持长连接并逐块推送数据;同步返回或普通循环会导致typeerror或连接秒断。

直接用 EventSourceResponse 就能跑通,但不处理连接生命周期和错误重试,上线后大概率断连没人收得到消息。
为什么 EventSourceResponse 必须配合异步生成器
FastAPI 的 SSE 要求响应体是一个异步可迭代对象(AsyncGenerator),不能是普通函数返回值或同步循环。浏览器建立连接后,会持续等待流式数据块,如果服务端阻塞或提前退出生成器,连接就立刻关闭。
- 错误写法:
return [{"data": "hello"}]或for i in range(5): yield ...(没加async) - 正确写法:必须用
async def定义生成器,且每个yield前建议加await asyncio.sleep(0)让出控制权 - 常见报错:
TypeError: 'list' object is not an async iterator或连接秒断无日志
ServerSentEvent 类比裸字典更可控的三个理由
直接 yield {"data": ...} 虽快,但没法设事件类型、ID、重连间隔等关键字段。用 ServerSentEvent 类才能真正符合 SSE 协议规范。
-
event字段决定客户端eventSource.addEventListener("progress", ...)绑定的事件名 -
id是断线重连时客户端自动携带的上一个事件 ID,服务器靠它做断点续推(需自行存状态) -
retry控制客户端重连间隔(毫秒),默认 3000,设太小易触发高频重连风暴
生产环境必须处理的两个连接问题
SSE 连接长,但不是“永远不断”。反向代理(如 Nginx)、负载均衡器、CDN 或客户端休眠都可能主动 kill 掉空闲连接,必须有兜底逻辑。
- 心跳保活:定期
yield ServerSentEvent(comment="keep-alive"),避免连接被中间件误判为死链 - 异常捕获:在生成器里包
try/except,遇到ClientDisconnect或ConnectionResetError时优雅退出,别让协程卡住占资源 - 别忽略
request.is_disconnected()检查 —— 它比等异常抛出更早感知断连
最易被忽略的是客户端重连行为:浏览器默认重试 3 秒,但不会传上次收到的 id 给服务器,除非你显式在 EventSource 构造时加 withCredentials: true 并配好 CORS,否则断线后所有历史进度都得从头开始。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











