Redux-saga 有条件地 takeLatest
Redux-saga takeLatest conditionally
我有一个与 redux-saga 相关的问题,有什么方法可以实现 takeLatest 但有条件。
例如,我有一个歌曲类型的动态列表(说唱、流行、Hip_hop...),我想按歌曲类型获取歌曲。我定义了一个类型为“FETCH_SONGS_BY_TYPE”的 redux-action,然后将 songType 传递给它。动作看起来像
// actions
const fetchSongsByType = songType => ({
type: FETCH_SONGS_BY_TYPE,
songType
});
--------------------------------------------------
//saga
function* fetchSongsByTypeSaga(action) {
// request songs list by action.songType
}
function* Saga() {
yield takeLatest(FETCH_SONGS_BY_TYPE, fetchSongsByTypeSaga);
}
所以我希望仅当下一个 saga 运行 具有相同的歌曲类型时才取消上一个 saga 任务。
在上面的代码中,我得到了这个:
- fetchSongs - 歌曲类型:Hip_hop(因 [2] 而取消)
- fetchSongs - 歌曲类型:Rap(因 [3] 而取消)
- fetchSongs - 歌曲类型:流行音乐(因 [4] 而取消)
- fetchSongs - 歌曲类型:Rap(因 [5] 而取消)
- fetchSongs - 歌曲类型:流行
但我预计它会是这样的:
- fetchSongs - 歌曲类型:Hip_hop
- fetchSongs - 歌曲类型:Rap(因 [4] 而取消)
- fetchSongs - 歌曲类型:流行音乐(因 [5] 而取消)
- fetchSongs - 歌曲类型:说唱
- fetchSongs - 歌曲类型:流行
感谢任何帮助,在此先感谢。
如果您查看 takeLatest 的文档,您将了解如何使用 low-level 效果构建此效果。使用此示例,您可以轻松创建自定义效果,该效果仅取消来自相同音乐流派的操作。
takeLatestByType:
const takeLatestByType = (patternOrChannel, saga, ...args) => fork(function*() {
// hold a reference to each forked saga identified by the type property
let lastTasks = {};
while (true) {
const action = yield take(patternOrChannel);
// if there is a forked saga running with the same type, cancel it.
if (lastTasks[action.type]) {
yield cancel(lastTasks[action.type]);
}
lastTasks[action.type] = yield fork(saga, ...args.concat(action));
}
});
用法:
function* Saga() {
yield takeLatestByType(FETCH_SONGS_BY_TYPE, fetchSongsByTypeSaga);
}
我有一个与 redux-saga 相关的问题,有什么方法可以实现 takeLatest 但有条件。
例如,我有一个歌曲类型的动态列表(说唱、流行、Hip_hop...),我想按歌曲类型获取歌曲。我定义了一个类型为“FETCH_SONGS_BY_TYPE”的 redux-action,然后将 songType 传递给它。动作看起来像
// actions
const fetchSongsByType = songType => ({
type: FETCH_SONGS_BY_TYPE,
songType
});
--------------------------------------------------
//saga
function* fetchSongsByTypeSaga(action) {
// request songs list by action.songType
}
function* Saga() {
yield takeLatest(FETCH_SONGS_BY_TYPE, fetchSongsByTypeSaga);
}
所以我希望仅当下一个 saga 运行 具有相同的歌曲类型时才取消上一个 saga 任务。
在上面的代码中,我得到了这个:
- fetchSongs - 歌曲类型:Hip_hop(因 [2] 而取消)
- fetchSongs - 歌曲类型:Rap(因 [3] 而取消)
- fetchSongs - 歌曲类型:流行音乐(因 [4] 而取消)
- fetchSongs - 歌曲类型:Rap(因 [5] 而取消)
- fetchSongs - 歌曲类型:流行
但我预计它会是这样的:
- fetchSongs - 歌曲类型:Hip_hop
- fetchSongs - 歌曲类型:Rap(因 [4] 而取消)
- fetchSongs - 歌曲类型:流行音乐(因 [5] 而取消)
- fetchSongs - 歌曲类型:说唱
- fetchSongs - 歌曲类型:流行
感谢任何帮助,在此先感谢。
如果您查看 takeLatest 的文档,您将了解如何使用 low-level 效果构建此效果。使用此示例,您可以轻松创建自定义效果,该效果仅取消来自相同音乐流派的操作。
takeLatestByType:
const takeLatestByType = (patternOrChannel, saga, ...args) => fork(function*() {
// hold a reference to each forked saga identified by the type property
let lastTasks = {};
while (true) {
const action = yield take(patternOrChannel);
// if there is a forked saga running with the same type, cancel it.
if (lastTasks[action.type]) {
yield cancel(lastTasks[action.type]);
}
lastTasks[action.type] = yield fork(saga, ...args.concat(action));
}
});
用法:
function* Saga() {
yield takeLatestByType(FETCH_SONGS_BY_TYPE, fetchSongsByTypeSaga);
}