面灵AI→

小米 AI 前端实习一面:流式渲染背压与团队 AI 协作

轮次
一面
结果
通过
时间
2026-09
来源
牛客网

《面试题目》

  1. 自我介绍。
  2. 共享屏幕手撕两道算法题:一道反转类题目,一道非 Hot 题。
  3. 防抖和节流分别用在什么场景?
  4. HTTP 协议底层用的是什么连接?
  5. WebSocket 是什么东西?特点是什么?
  6. SSE 是什么?有什么场景下能用到?
  7. 平时代码管理器用的什么?
  8. git merge 和 git rebase 的区别?它们各自的特点?
  9. 提交完发现有问题,要从 master 上撤回来,用什么?
  10. 在界面上怎么去调试性能问题?比如今天页面突然很卡,你怎么排查?
  11. 自上而下和调用树之间的区别?了解过这两个吗?它排查下来是怎么用的?
  12. 平时用 React 多吗?Vue 的基本原理是什么?它是怎么做渲染的?
  13. 你有完整部署过一个项目吗?
  14. 反向代理和正向代理的区别?
  15. 做过流式输出对话的那些界面吗?
  16. 项目是干嘛用的?
  17. React 架构是干什么的?那个 loop 又是什么?跟 React 有什么关系?
  18. 场景题:大模型在 100 毫秒内吐了 1000 次,吐太快会导致前端界面卡顿,这种情况怎么优化?用什么方式?什么数据结构?(面试官补充的比喻:上游供给端是个大坝,供水过多,下游界面的消费能力有限)
  19. Vue 框架什么时候会触发复用 DOM 节点?
  20. 场景题:假设有个上百人的团队,每个人每天都用 AI 写代码,有些情况下需要人为提供经验。有些对话会发现 AI 改错了,我们希望这类经验能被所有人复用——发现问题、补充进去、所有人都能得知。这套团队知识体系建设如果是你来做,会从哪些方向或者架构理念切入?
  21. 如何保证在 AI 写代码的情况下,线上不会出事故?如何保证质量?
  22. 如果管了 100 个团队,你一个一个去 review 吗?
  23. 了解端到端测试吗?无头浏览器听过没?
  24. 反问环节:公司的业务?全栈趋势?

《参考解析》

流式渲染的背压(第 18 题):这是整套题里最有含量的一道。问题本质是生产速度远大于渲染速度,直接每来一个 token 就 setState,会让 React 在 100ms 内触发上千次渲染,主线程被 reconciliation 占满,页面自然卡。解法分三层:

  1. 不每次渲染,做批量合并。最简单的是定时刷新——用 requestAnimationFrame 或固定间隔(16ms / 50ms)把这一段时间内到达的 token 一起提交,把渲染频率从”每个 token 一次”压到”每帧一次”。也可以用微任务合并(在一个 microtask 里累积、下一个 microtask 统一 flush)。
  2. 削峰的数据结构:用一个队列(数组)当缓冲区,token 到达就入队,渲染循环按帧从队头取出并拼接;队列长度就是水位,可以用来做反馈。大坝那个比喻对应的正是”缓冲区 + 按消费能力消费”,超出水位时就该让消费端表态(比如暂停上游读取)。
  3. 真正的背压:如果上游是 SSE / fetch stream,可以用 ReadableStream 的 pull 语义——消费端不 ready 就不拉下一块;WebSocket 侧则可以在水位过高时发一条”暂停”信号给服务端,让服务端降低发送速率。此外还有渲染侧的优化:把已定稿的段落拆成不随流的静态组件并 memo,只让最后一段参与高频更新;用 useDeferredValue 或 transition 把非紧急更新降级;文本用 textarea + value 直接赋值这类不触发 diff 的方式。答题时把”合并渲染 → 缓冲队列 → 反馈上游”这三步说出来,比只答”用防抖”完整得多。

WebSocket 与 SSE:WebSocket 是全双工、基于 TCP 的独立协议(一次 HTTP 升级握手后长连),适合双向实时交互,比如协同编辑、聊天、游戏状态同步;SSE 是单向的服务端推送(基于普通 HTTP 的 text/event-stream),浏览器原生 EventSource 支持自动重连和事件 id,适合”服务端持续下发、客户端只听”的场景,比如 AI 对话流式输出、进度通知、行情推送。选型看方向性:只需要服务端推就用 SSE(实现简单、能过大多数代理),需要双向就上 WebSocket。

git merge 与 rebase:merge 保留真实历史并生成一个合并提交,历史呈分叉结构,适合主干合并分支;rebase 把当前分支的提交”搬”到目标分支最新提交之后,历史是一条直线,可读性好,但会重写提交哈希——所以绝不要对已经推送并被他人使用的公共分支做 rebase。撤回方面,还没推送时用 git reset(--soft 保留改动、--hard 丢弃)或 git commit --amend;已经推送则用 git revert 生成一个反向提交,不要在共享分支上 reset 后强推。

性能卡顿怎么查:先用 Performance 面板录一段卡顿期间的操作,看主线程上是谁在占用——长任务(Long Task)会直接标红。常见元凶是频繁的布局抖动(反复读写 offsetHeight 触发强制重排)、过大的列表没有虚拟化、高频事件(scroll / resize / mousemove)没做节流、以及大量 DOM 节点同时更新。调用树(Call Tree)适合看”哪个函数累计耗时最多”,自下而上(Bottom-Up)适合看”哪个函数被调用了最多次 / 自身耗时最高”,两者配合能快速定位到热点函数而不是只看表层。

团队级 AI 知识体系(第 20 题):可以做成一个闭环:沉淀——把”AI 改错了并且被人工纠正”的对话自动抽取成结构化条目(场景、错误模式、正确做法、涉及文件),而不是存原始聊天记录;分发——按模块 / 技术栈打标签,落到代码仓库的约定文件(如目录级规则)、评审 checklist 和 AI 助手的系统提示里,让下一次生成时就能读到;生效验证——同样的场景重跑一遍,看是否还会犯;治理——有 owner、有去重与过期机制,避免规则越堆越多把模型带偏。核心认知是:给 AI 的规则要少而准,一条经验要能说清”什么情况适用、为什么”,否则所有模型会长成同一个样子。

如何保证 AI 写的代码不出事故(第 21 题):不能靠”让人逐个 review”。有效的组合是:把 correctness 前移到可机器验证的环节——类型检查、lint、单测、构建门禁必须全绿才能合;关键路径加端到端探针和发布后的 canary;对数据库迁移、支付、权限这类高风险改动做改动面识别,命中了就必须人审;再配合灰度发布与快速回滚能力。另外要接受”AI 会犯错是常态”,所以设计的重点不是”让它不犯错”,而是”错了能很快被发现并回滚”——可观测性、回滚演练、变更审计比 review 更兜底。