← ✦ UX 交互模式 · 那些有名字的交互细节 / Optimistic UI:先更新界面,再等服务器 待审核 1 / 7
optimistic · 乐观更新

Optimistic UI:先更新界面,再等服务器

点赞、收藏、勾选待办这类操作,失败率极低。既然几乎总会成功,为什么要让用户盯着 spinner 等服务器?乐观更新 (Optimistic UI) 的策略是:点击瞬间就把界面更新到「成功后的样子」,把真正的请求挪到后台;只有在真的失败时才回滚并提示。下面同一个点赞按钮,在「乐观」与「悲观」两种策略下、同样的网络延迟里,体感完全不同。

乐观策略下,UI 在 t+0 就更新了,网络延迟被完全藏在背后;只有命中那次注定失败的请求,才会在响应到达时回滚——这正是它的代价:偶发的「跳一下」。悲观策略永远正确,但每次操作都要付出全额延迟,且按钮在等待期 disabled。两者的取舍由失败的后果决定:点赞错了无伤大雅 → 乐观;转账金额 → 必须悲观。

乐观更新的骨架——先改 UI,失败再回滚:

async function like() {
  const prev = snapshot(state);
  applyChange(state);          // 1. 立即更新 UI
  render();
  try {
    await api.toggleLike();    // 2. 后台发请求
  } catch (err) {
    restore(state, prev);      // 3. 失败回滚
    render();
    toast('网络错误,已撤销');   // 4. 失败信号
  }
}

乐观更新的三个必备零件,缺一不可:其一,操作前快照旧状态 (prev);其二,失败时精确回滚到快照(并处理回滚期间用户又点了的竞态);其三,给用户一个失败信号——通常就是一条 Snackbar。若服务器返回的「真实值」和乐观猜测不同(如点赞数被别人同时改了),还要用响应数据校正,而不是简单确认。

它和 Yellow Fade 是互补的:乐观更新负责让变化来得快,Yellow Fade 负责让变化被看见。许多数据库 / 框架已内建这一模式(React 的 useOptimistic、SWR / React Query 的 optimistic mutation),但理解上面三个零件,才知道它们在替你做什么。