React提供更优雅的前端代码书写方式和更优的界面更新机制,redux提供了组件和业务分离的解决方案,saga或thunk基于redux提供异步业务实现方案。
流程图
图中的Middleware工作于redux内部,介于action和reducer之间,而saga只是某一种Middleware。
saga工作于action和reducer之间。如果按照原始的redux工作流程,当组件中产生一个action后会直接触发reducer修改state;而往往实际中,组件中发生的action后,在进入reducer之前需要完成一个异步任务,原生的redux不支持这种操作。
不过,实现异步操作的整体步骤是很清晰的:action被触发后,首先执行异步任务,待完成后再将这个action交给reducer。说到这里,thunk和saga的达到的效果是一致的,差别在于对action的处理完全不一样。
thunk采用的是扩展action的方式:使得redux的store能dispatch的内容从普通对象扩展到函数。
const mapDispatchToProps = dispatch => {
return {
delayData: () => dispatch(delayData)
};
};
const delayDataAction = {
type: DALAY_DATA
};
export const delayData = dispatch => {
delayDataTask(dispatch, delayDataAction);
};
saga采用的方案更接近于redux的全局思想,使用方式和thunk有很大不同:
saga需要一个全局监听器(watcher saga),用于监听组件发出的action,将监听到的action转发给对应的接收器(worker saga),再由接收器执行具体任务,任务执行完后,再发出另一个action交由reducer修改state,所以这里必须注意:watcher saga监听的action和对应worker saga中发出的action不能是同一个,否则造成死循环。
在saga中,全局监听器和接收器都使用Generator函数和saga自身的一些辅助函数实现对整个流程的管控。
整个流程可以简单描述为:
Component —> Action1 —> Watcher Saga —> Worker Saga —> Action2 —> Reducer —> Component
相比thunk,saga是多了一个action的,因为saga是将业务的触发(watcher saga)和业务的执行(worker saga)分开描述的。
const getCountAction = (param) => {
return {
type: 'count',
param
}
}
const getCountFinishAction = (param) => {
return {
type: 'countFinish',
param
}
}
const mapDispatchToProps = (dispatch) => {
return {
count: (param) => {
return dispatch(getCountAction(param))//这里dispatch的参数是个普通对象
}
}
}
//一个普通函数 将当前计数+1
function counter(curCount) {
return ++curCount
}
//worker saga 这里其实是有接收参数的 这个参数action就是redux执行dispatch方法中的参数
function* counterSaga(action) {
console.log(`counterSaga receive the action ${action.type}`)
//接受到这个action之后 执行saga的call方法 call方法会执行counter函数 并将当前计数作为它的参数
const countResult = yield call(counter, action.param)
//counter执行的结果作为另一个action的参数
yield put(getCountFinishAction(countResult))
}
//watcher saga 监听takeEvery这个action 并执行helloSaga
function* watchIncrementAsync() {
console.log('watcher saga is listening to action')
yield* takeEvery('count', counterSaga);
}
//执行watcher saga 这样就可以一直监听应用中的action了
sagaMiddleware.run(watchIncrementAsync)
网友评论