标准答案
- Redux reducer 必须保持纯函数,异步请求、日志、埋点等副作用应放在中间件或外部逻辑中。
- 中间件通过包装 dispatch 形成链式调用,可以在 action 到达 reducer 前后执行额外逻辑。
- Thunk 允许 dispatch 一个函数,在函数里拿到 dispatch 和 getState,适合简单异步请求。
- Saga 使用 generator 描述副作用流程,适合复杂编排、取消、并发、节流和长事务。
- Thunk 简单直接,Saga 表达能力强但概念成本更高。
题目解析
这道题可以从“Redux 本身只管理同步状态变更”讲起。中间件是副作用进入 Redux 流程的入口。
Thunk 更像把异步逻辑写成普通函数,学习成本低;Saga 更像声明一套可测试、可取消的流程。
如果项目异步逻辑只是普通 CRUD,Thunk 或 RTK Query 往往已经够用;复杂业务流程才更需要 Saga。
代码示例
下面的 Thunk 在请求成功后派发 fulfilled action。
TypeScript
export const loadUser = (id: string) => async (dispatch: AppDispatch) => {
dispatch(userActions.loading())
try {
const user = await fetchUser(id)
dispatch(userActions.loaded(user))
} catch (error) {
dispatch(userActions.failed(normalizeError(error)))
}
}常见误区
- 在 reducer 里发请求或写副作用,破坏 Redux 可预测性。
- 简单请求也引入 Saga,增加没有必要的心智负担。
- 异步 action 没有统一错误结构,页面无法稳定处理失败状态。