Skip to content

Next.js AI 项目实践

Next.js AI 对话如何实现流式输出、恢复和取消?

高级实现要把浏览器流、Route Handler、上游模型和持久化任务连起来,而不是只在页面里 append 字符串。

适合阶段:资深前端 / AI 全栈面试核心能力:Route Handler · Stream · Recovery

面试官想考什么

  • Next.js 中 SSE 和 Fetch Stream 怎么选? 考察协议与部署。
  • 如何把上游模型流转发给浏览器? 考察背压和错误。
  • 断线后怎样避免重复生成? 考察任务 id 与游标。
  • AbortSignal 如何贯穿整条链路? 考察取消语义。

一句话回答

text
Route Handler 创建带 requestId 的生成任务并返回规范化事件流,上游 provider 的 AbortSignal 与客户端取消关联;服务端按 sequence/cursor 保存 checkpoint,断线时重放或返回最终快照,前端据此去重和恢复。

面试回答详解

1. Route Handler 边界

text
POST /api/chat -> auth/idempotency -> provider stream
-> transform events -> Response(ReadableStream)
-> checkpoint/final message

Route Handler 负责 HTTP、鉴权、流格式和错误映射,不应该让浏览器接触 provider key 或内部异常。

2. 事件协议

每个事件包含 type、requestId、messageId、sequence 和 data。文本、工具调用、引用、完成、取消和错误分开,客户端不能靠字符串猜状态。

3. 取消和断线

客户端 AbortController 只会停止 fetch;Route Handler 要捕获断开并将取消信号传给 provider。服务端仍可能已经产生部分内容,因此保存 cancelled 状态。断线重连带 cursor,若事件不可重放则查询任务快照。

4. 缓冲和性能

上游 chunk 不等于事件,先做解码与协议缓冲。前端按窗口批量更新,服务端 checkpoint 也不能按 token 写数据库。流响应要设置心跳、超时和代理缓冲策略。

5. 错误与部署

区分客户端取消、上游超时、provider 429、鉴权失败和解析失败。确认目标平台支持长响应和 flush;不支持时改为 job + polling。记录 TTFT、断开率、重连次数和 resume gap。

可直接背诵的 30 秒回答

text
我会用 Route Handler 做鉴权后的流式 BFF,事件带 requestId、messageId 和 sequence,先解析上游 chunk 再转成稳定协议。客户端 abort 后服务端继续向 provider 传播 AbortSignal;服务端按 checkpoint 保存状态,重连带 cursor 做重放,不能重复调用模型。部署还要验证代理是否支持 flush、超时和长连接。

扩展知识

SSE 与 Fetch Stream

  • SSE:事件语义和浏览器重连模型更直接,服务端单向推送。
  • Fetch Stream:适合 POST body、控制器和自定义协议。
  • 选择还要看代理、CDN、平台时限和客户端兼容。

面试官追问链

追问一:客户端断开后服务端一定知道吗?

  • 考察点:连接生命周期。
  • 回答方向:通常可以通过 request signal/连接关闭感知,但存在延迟和竞态;必须有服务端超时和任务状态兜底。

追问二:为什么不能直接重试 POST?

  • 考察点:重复生成。
  • 回答方向:先用幂等键查询原任务状态,重试连接或恢复事件,不要盲目创建第二次模型调用。

追问三:Edge Runtime 一定更适合流式吗?

  • 考察点:运行时误区。
  • 回答方向:网络首字节可能有优势,但 API、依赖、长任务和数据库能力有限,应按 provider、平台和任务时长选择。

推荐阅读

基于 MIT 协议开源