如何重构redux-saga生成器函数?新手优化重复逻辑求助
嘿,我完全懂你现在的烦恼——重复的saga代码不仅冗余,后期维护起来也麻烦。咱们来把这段代码好好重构一下,把重复的核心逻辑抽离出来,同时保留takeLatest和takeEvery各自的特性。
重构思路与实现
首先拆解重复部分:两个处理生成器setRandomColourGeneratorLatest和setRandomColourGeneratorEvery,除了判断sagaType的条件不同,核心的「延迟+dispatch动作」逻辑完全一致。我们可以把核心逻辑单独抽离,再用工厂函数生成对应不同saga类型的处理函数。
1. 抽离核心业务逻辑
把延迟后更新颜色的逻辑单独写成一个独立生成器,它只负责接收必要参数(id和延迟时间),执行具体操作:
function* handleSetRandomColour(id, ms) { console.log("set random colour", id, ms); yield call(delay, ms); yield put(setRandomColour(id)); }
2. 用工厂函数生成类型专属处理函数
写一个工厂函数,传入目标sagaType(比如'takeLatest'或'takeEvery'),返回对应的处理生成器。这个生成器会先判断action的sagaType是否匹配,匹配则调用抽离的核心逻辑:
function createSetRandomColourHandler(targetSagaType) { return function* handler({ payload: { id, ms, sagaType } = {} } = {}) { if (sagaType !== targetSagaType) return; // 用call调用核心生成器,确保yield流程正确执行 yield call(handleSetRandomColour, id, ms); }; }
3. 简化监听逻辑
现在可以直接用工厂函数生成所需的处理函数,绑定到对应的takeLatest/takeEvery上,甚至可以省略单独的watch函数,直接在rootSaga里配置:
import { put, takeEvery, takeLatest, all, call } from 'redux-saga/effects'; import { setRandomColour, SET_RANDOM_COLOUR_DELAYED } from './actions'; const delay = (ms) => new Promise(res => setTimeout(res, ms)); // 核心逻辑生成器 function* handleSetRandomColour(id, ms) { console.log("set random colour", id, ms); yield call(delay, ms); yield put(setRandomColour(id)); } // 工厂函数生成处理函数 function createSetRandomColourHandler(targetSagaType) { return function* handler({ payload: { id, ms, sagaType } = {} } = {}) { if (sagaType !== targetSagaType) return; yield call(handleSetRandomColour, id, ms); }; } // 根saga export default function* rootSaga(){ yield all([ takeLatest(SET_RANDOM_COLOUR_DELAYED, createSetRandomColourHandler('takeLatest')), takeEvery(SET_RANDOM_COLOUR_DELAYED, createSetRandomColourHandler('takeEvery')) ]) }
为什么之前的尝试可能失败?
你提到抽离逻辑后无法正常运行,大概率是因为调用核心生成器时没有用yield call()或者yield*。生成器函数调用后返回的是迭代器对象,必须通过yield驱动它执行所有的yield步骤;如果直接写handleSetRandomColour(id, ms)而没有yield,这个生成器根本不会被执行,自然看不到预期效果。
这样重构后,核心逻辑只需要维护一次,后续如果要加更多类似的saga类型,只需要调用工厂函数生成对应处理函数即可,非常方便。
内容的提问来源于stack exchange,提问作者George

