2021年开发搭配redux-toolkit时应选redux-saga还是redux-thunk?
Redux Toolkit 下 redux-thunk 与 redux-saga 选型参考
先说核心结论:Redux Toolkit 场景下优先默认使用内置的 thunk,仅在有明确复杂异步需求时再考虑引入 saga。
一、redux-thunk 适用场景
- 简单异步逻辑开发:比如普通的单接口请求、按顺序执行少量异步操作,thunk 写法最简洁,没有额外的学习成本,且 Redux Toolkit 默认内置
redux-thunk,不需要额外安装配置,配合createAsyncThunk可以快速实现需求。 - 中小项目、团队对 Redux 生态不熟悉的场景:thunk 本质就是普通的 JS 函数,会写 async/await 就能上手,项目后续维护成本很低。
- 无复杂异步控制需求:如果你的异步逻辑只有「发请求→成功更新store→失败抛提示」的流程,thunk 完全够用,代码量比 saga 少 50% 以上。
给个 RTK 下 thunk 的常规写法示例:
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit' import { fetchUserApi } from './api' // 直接定义异步请求逻辑 export const fetchUser = createAsyncThunk('user/fetchUser', async (userId) => { const res = await fetchUserApi(userId) return res.data }) const userSlice = createSlice({ name: 'user', initialState: { data: null, loading: false, error: null }, extraReducers: (builder) => { builder .addCase(fetchUser.pending, (state) => { state.loading = true }) .addCase(fetchUser.fulfilled, (state, action) => { state.loading = false state.data = action.payload }) .addCase(fetchUser.rejected, (state, action) => { state.loading = false state.error = action.error.message }) } })
二、redux-saga 适用场景
- 复杂异步流控制需求:比如要做请求防抖/节流、重复请求自动取消、多个异步任务并行/串行调度、监听特定 action 触发连锁异步操作,这类逻辑用 thunk 写会非常臃肿,还容易出现内存泄漏问题,saga 内置的
takeLatest/debounce/cancel等 effect API 可以非常优雅的实现这些需求。 - 长期运行的异步任务:比如 websocket 长连接监听、全局消息轮询、全局请求拦截(比如未登录时拦截所有接口请求跳转登录页),saga 可以把这类逻辑抽离为独立的任务,和业务组件完全解耦,维护更方便。
- 大型项目对可测试性要求高的场景:saga 的异步逻辑都是声明式编写,单测不需要 mock 接口,只要验证 saga 是否 yield 了对应的 effect 即可,测试成本比 thunk 低很多。
给个防抖搜索的 saga 写法示例:
import { debounce, call, put } from 'redux-saga/effects' import { searchApi } from './api' import { searchSuccess, searchFailed } from './searchSlice' function* handleSearch(action) { try { const res = yield call(searchApi, action.payload) yield put(searchSuccess(res.data)) } catch (e) { yield put(searchFailed(e.message)) } } function* watchSearch() { // 用户输入停止300ms后再发请求,重复触发自动取消上一次未完成的请求 yield debounce(300, 'search/triggerSearch', handleSearch) }
同样的逻辑用 thunk 实现需要自己维护定时器、请求取消的 AbortController,代码量会大很多,也更容易出 bug。
三、最终选型建议
- 如果你的项目没有上面提到的 saga 专属复杂异步需求,直接用 RTK 内置的 thunk 即可,不要额外引入 saga 增加项目复杂度,目前 90% 的业务项目用 thunk 都完全够用。
- 如果你已经遇到了 thunk 写异步逻辑非常吃力的情况,再引入 saga 即可,两者也可以在项目中共存,不需要全量替换已有逻辑。
- 额外补充:Redux Toolkit 自带的 RTK Query 已经覆盖了大部分通用接口请求的缓存、去重、取消逻辑,优先用 RTK Query 处理普通接口请求,特殊复杂异步场景再根据需求选 thunk 或者 saga 即可。
内容的提问来源于stack exchange,提问作者Dima Kambalin
相关产品推荐
相关产品推荐

