Redux-Saga进阶指南:Saga的组合与并行控制
redux-saga 项目地址: https://gitcode.com/gh_mirrors/red/redux-saga
理解Saga的组合模式
在Redux-Saga中,组合多个Saga是构建复杂异步流程的基础能力。开发者最初可能会使用yield*
语法来实现Saga的组合,这种方式确实提供了一种直观的生成器组合方式,但它存在两个明显的局限性:
- 测试困难:嵌套的生成器难以单独测试,会导致测试代码重复和额外的执行开销
- 串行限制:一次只能组合一个生成器,无法实现并行控制
更优的组合方式:yield与effect组合
基础组合模式
使用yield
调用子Saga是最基础的组合方式,父Saga会等待子Saga完成后再继续执行:
function* parentSaga() {
// 等待childSaga执行完毕
const result = yield call(childSaga)
// 处理子Saga返回的结果
yield put(someAction(result))
}
这种方式适用于需要严格顺序执行的场景,其中call
effect会阻塞父Saga直到子Saga完成。
并行执行模式
当需要同时执行多个独立任务时,可以使用all
effect实现并行控制:
function* parallelTasks() {
// 同时启动三个任务,等待全部完成
const [result1, result2, result3] = yield all([
call(task1),
call(task2),
call(task3)
])
// 处理所有结果
yield put(combinedAction(result1, result2, result3))
}
all
effect类似于Promise.all,它会并行启动所有子任务,并等待它们全部完成后再继续执行。
竞态条件处理
在实际应用中,经常需要处理超时或竞态条件。race
effect提供了优雅的解决方案:
function* fetchWithTimeout() {
const {data, timeout} = yield race({
data: call(fetchData),
timeout: delay(5000) // 5秒超时
})
if (timeout) {
yield put(fetchTimeout())
} else {
yield put(fetchSuccess(data))
}
}
这个模式特别适合需要设置超时或处理先到先得场景的应用。
实际应用示例
游戏场景实现
考虑一个游戏场景,玩家需要在限定时间内完成游戏:
function* gameSaga() {
let gameCompleted = false
while (!gameCompleted) {
// 60秒内必须完成游戏
const {score, timeout} = yield race({
score: call(playGame),
timeout: delay(60000)
})
if (!timeout) {
gameCompleted = true
yield put(showFinalScore(score))
} else {
yield put(gameOver())
}
}
}
复杂数据获取
当需要从多个API获取数据并组合时:
function* loadDashboard() {
// 并行获取用户信息和通知
const [user, notifications] = yield all([
call(fetchUser),
call(fetchNotifications)
])
// 根据用户信息获取个性化内容
const personalizedContent = yield call(fetchContent, user.id)
yield put(dashboardLoaded(user, notifications, personalizedContent))
}
最佳实践建议
- 合理划分Saga粒度:每个Saga应专注于单一业务逻辑
- 优先考虑并行:独立任务尽量使用
all
并行执行 - 处理竞态条件:关键操作应使用
race
添加超时保护 - 保持Saga纯净:避免在Saga中直接执行副作用操作
- 合理组合effects:灵活组合
call
、all
、race
等effect构建复杂流程
通过掌握这些组合模式,开发者可以构建出既清晰又强大的异步流程控制,满足各种复杂业务场景的需求。
redux-saga 项目地址: https://gitcode.com/gh_mirrors/red/redux-saga
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考