在多个效果之间开始竞速
有时我们会并行启动多个任务,但我们不想等待所有任务完成,我们只需要获得获胜者:第一个完成(或拒绝)的任务。race
效果提供了一种在多个效果之间触发竞赛的方法。
以下示例展示了一个触发远程获取请求的任务,并将响应限制在 1 秒超时时间内。
import { race, call, put, delay } from 'redux-saga/effects'
function* fetchPostsWithTimeout() {
const {posts, timeout} = yield race({
posts: call(fetchApi, '/posts'),
timeout: delay(1000)
})
if (posts)
yield put({type: 'POSTS_RECEIVED', posts})
else
yield put({type: 'TIMEOUT_ERROR'})
}
race
的另一个有用功能是它会自动取消失败的效果。例如,假设我们有 2 个 UI 按钮
第一个在后台启动一个在无限循环
while (true)
中运行的任务(例如,每隔 x 秒与服务器同步一些数据)。后台任务启动后,我们将启用第二个按钮,该按钮将取消该任务
import { race, take, call } from 'redux-saga/effects'
function* backgroundTask() {
while (true) { ... }
}
function* watchStartBackgroundTask() {
while (true) {
yield take('START_BACKGROUND_TASK')
yield race({
task: call(backgroundTask),
cancel: take('CANCEL_TASK')
})
}
}
如果分发了 CANCEL_TASK
操作,race
效果将通过在其中抛出取消错误来自动取消 backgroundTask
。