2025 年大厂必考题:流式输出到底是什么?前端手把手教你实现

21 阅读5分钟

还在纠结大模型聊天机器人为什么能 “边说边出字”?想知道为什么这道题成了 25 年大厂面试的香饽饽?吃透 “流式输出”—— 从原理到全栈实战,让你的前端项目体验直逼 ChatGPT!

一、为什么流式输出成了大厂必考题?

先看一组趋势:23 年 AI 大模型爆火,24 年聚焦推理优化,25 年AI Agent(智能代理)成为新风口。而流式输出,正是 AI 产品用户体验的 “灵魂技能”。

核心原因:

  • 大模型的特性决定的:LLM(大语言模型)生成内容时,是像人说话一样 “一个词一个词蹦”(专业叫 “token-by-token” 生成),不会一次性吐出完整内容。
  • 前端的核心职责:用户体验。流式输出能让用户 “边等边看”,而不是盯着空白屏幕发呆 —— 这正是大厂考核 “用户体验设计” 的关键考点。

二、为什么需要流式输出?举个栗子就懂

想象两个聊天机器人:

  • 传统方式:你发消息后,屏幕空白 3 秒,突然一次性弹出 100 字回复。
  • 流式输出:你发消息后,屏幕立刻开始 “打字”,1 秒出几个字,3 秒内慢慢显示完 100 字。

生成前端封面图.png

你选哪个?显然是后者!
这就是流式输出的核心价值:把 “等待” 变成 “渐进式体验” ,用心理学降低用户的焦虑感 —— 哪怕总耗时一样,体验也天差地别。

流式输出的本质:从 “一次性” 到 “分批次”

传统的 HTTP 请求是 “一问一答”

  1. 前端发请求 → 后端处理 → 后端一次性返回所有数据 → 前端显示。

流式输出则是 “边处理边返回”

  1. 前端发请求 → 后端启动处理 → 后端生成一点数据就返回一点 → 前端收到一点就显示一点 → 直到全部返回。

就像喝水:传统方式是 “等水壶装满再一口气喝完”,流式输出是 “打开水龙头,边接边喝”。

三、前端如何实现流式输出?核心技术揭秘

前端要做的是:持续接收后端分批发来的数据,并实时更新到页面。现代浏览器提供了一个专门的 API——SSE(Server-Sent Events,服务器发送事件)

简单说:SSE 就是 “后端给前端发消息的通道”

  • 前端创建一个 “事件源”,连接后端的 SSE 接口;
  • 后端通过这个接口,随时给前端 “推消息”;
  • 前端收到消息后,立刻更新页面。

四、全栈实战:从 0 实现流式输出

我们用前端 HTML + 后端 Node.js(Express)  实现一个 “实时报时” 的流式输出案例:后端每秒推一次当前时间,前端实时显示。

步骤 1:搭建后端(Node.js+Express)

1. 初始化项目

# 初始化npm
npm init -y
# 安装express框架
npm i express

2. 后端代码(index.js)

// 引入express框架
const express = require('express');
const app = express(); // 创建后端应用

// 1. 前端页面路由:访问localhost:3000时返回HTML页面
app.get('/', (req, res) => {
  // 发送前端页面(后面会创建index.html)
  res.sendFile(__dirname + '/index.html');
});

// 2. SSE接口:专门用于后端向前端推数据
app.get('/sse', (req, res) => {
  // 设置响应头:告诉前端这是SSE流
  res.set({
    'Content-Type': 'text/event-stream', // 固定格式:声明是事件流
    'Cache-Control': 'no-cache', // 禁止缓存,确保数据实时
    'Connection': 'keep-alive' // 保持连接,不中断
  });
  
res.flushHeaders(); // 立即发送这些响应头

  // 每1秒向前端推一次当前时间(模拟流式输出)
  setInterval(() => {
    // SSE数据格式:必须以`data: 内容\n\n`结尾
    const time = new Date().toLocaleTimeString(); // 当前时间
    res.write(`data: <p>${time}</p>\n\n`); // 推送给前端
  }, 1000);
});

// 启动服务器,监听3000端口
app.listen(3000, () => {
  console.log('后端启动成功:http://localhost:3000');
});

步骤 2:编写前端页面(index.html)

<!DOCTYPE html>
<html>
<head>
  <title>流式输出演示</title>
</head>
<body>
  <h1>实时时间(流式输出)</h1>
  <div id="messages"></div> <!-- 用于显示流式数据 -->

  <script>
    // 1. 创建SSE连接:连接后端的/sse接口
    const source = new EventSource('/sse');

    // 2. 监听后端推送的消息
    source.onmessage = function(event) {
      // event.data就是后端推来的内容(这里是带<p>标签的时间)
      const messagesDiv = document.getElementById('messages');
      messagesDiv.innerHTML += event.data; // 实时添加到页面
    };
  </script>
</body>
</html>

运行效果

  1. 终端执行 node index.js 启动后端;
  2. 浏览器打开 http://localhost:3000,会看到页面每秒新增一行当前时间 —— 这就是最基础的流式输出!

image.png

image.png

五、关键技术点解析

1. 后端 SSE 接口的 3 个核心响应头

res.set({
  'Content-Type': 'text/event-stream', // 告诉前端:这是事件流,要持续接收
  'Cache-Control': 'no-cache', // 不缓存,每次都要新数据
  'Connection': 'keep-alive' // 保持TCP连接不关闭,才能持续推数据
});

这三个头是 “保持连接” 的关键,缺一不可。

2. 后端推数据的格式

必须用 data: 内容\n\n 格式,比如:

res.write(`data: 这是一条消息\n\n`); // 正确格式

\n\n 是结束符,告诉前端 “这一段数据发完了”。

3. 前端的 EventSource

const source = new EventSource('/sse'); // 连接后端SSE接口
source.onmessage = (event) => { ... } // 收到数据时触发
  • 自动保持连接,断了会自动重连;
  • 只能接收后端推送,不能主动发消息(适合单向流场景,如大模型回复)。

六、总结

对前端来说,流式输出的本质是:用 SSE(或 WebSocket)建立 “长连接”,实时接收后端分批数据,并即时更新 UI

它不只是一种技术,更是一种 “用户体验设计思维”—— 在等待不可避免时,想办法让用户 “不觉得在等”。

不止 AI 聊天:

  • 长文本加载:小说网站 “边翻页边加载” 下一章内容;
  • 实时日志:后台系统实时显示服务器日志,不用刷新页面;
  • 进度提示:文件上传时,实时显示 “已上传 30%”“50%”。

25 年大厂考这个,正是因为 AI 时代,这种 “渐进式体验” 会成为前端的基础能力。现在就动手试试上面的代码,感受一下流式输出的魅力吧!