redux-saga基本用法

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)

你可能感兴趣的:(redux-saga基本用法)