saga函数就是一些指令的集合,称为effects,副作用,用来描述任务
副作用 Side Effects 主要指的就是
- 异步网络请求
- 本地读取 localStorage/Cookie
reducers 纯函数
reducer有2个参数
- 第一个是,当前的 state状态
- 第二个是 ,payload 参数
reducers是唯一可以修改 state的,
- reducer里面不能调用,其他 reducer
- effect里面可以调用,其他 effect
effect里面通过,yield put(action),本质上就是 dispatch(action) 触发 state
reducers: {save(state, payload) {return {...state,...payload,}}}
effects
effects,副作用对象,里面放的都是 generator函数
effect函数有 2个参数,
- 第一个参数是,action对象
第二个参数是,effects对象,可以结构出来
- call,用来调用一个方法
- put,用来派发一个新的 action,等价于 dispatch({type: ‘’, payload})
- put里面可以调用 另外一个 effects方法
- select,选择一个命名空间
- all,类似 Promise.all 调用多个方法
```jsx effects: {
- init(action, effect) {
} } ```
- yield call 表示调用异步函数,
- yield all([]) 调用多个异步函数
- yield put 表示 dispatch(action)
- yield select, 用来访问其它 model,获取当前 state的数据
- take,
- fork,
- cancel
call 和 put 是saga的API,call负责调用 ajax
put 相当于dispatch,但是并不是真正执行dispatch,只是发送你指定的指令,交由saga中间件来执行这个指令
// effect格式*func (action, effects) => void// async异步方法effects: {// *asyncAdd(action, effect) {*asyncAdd(action, {call, put, select}) {const { call, put } = effectyield call(lazy) // 等待一秒钟// effects里面 type不需要加 namespaceyield put({ type: 'counter/add', payload: 100 })},}
- 在Effects里,Generator函数通过yield命令将异步操作同步化,
- 无论是yield 亦或是 async 目的只有一个: 让异步编写跟同步一样 ,从而能够很好的控制执行流程
- *query(action, {call, put, select}){}表示一个worker Saga,监听所有的query action, 并触发一个ApI 调用以获取服务器数据
yield
saga使用了 Generator迭代器,解决异步回调地狱,做到了异步代码以同步书写
// 延迟执行,msconst lazy = (time = 1000) =>new Promise(resolve => setTimeout(() => resolve(true), time))app.model({namespace: 'counter',state: { number: 0 },// 同步的方法reducers: {// state是之前的状态,return返回值是新状态 stateadd(state, action) {return { number: state.number + (action.payload || 10) }},},// async异步方法effects: {*asyncAdd(action, effect) {const { call, put } = effectyield call(lazy) // 等待一秒钟// effects里面 type不需要加 namespaceyield put({ type: 'counter/add', payload: 100 })},}})

监听 counter/asyncAdd,监听之后,执行 saga
takeEvery('counter/asyncAdd', *asyncAdd(action, effects));
subscriptions 订阅数据源
Subscriptions 表示订阅,用于订阅一个数据源,然后按需 dispatch action
- 格式为 ({ dispatch, history }) => unsubscribe
比如:当用户进入 /y/monthCard/list 页面时,触发 action query 加载数据
app.model({namespace: 'counter',state: { number: 0 },// 同步的方法reducers: {// state是之前的状态,return返回值是新状态 stateadd(state, action) {return { number: state.number + (action.payload || 10) }},},// async异步方法effects: {*asyncAdd(action, effect) {const { call, put } = effectyield call(lazy) // 等待一秒钟// effects里面 type不需要加 namespaceyield put({ type: 'counter/add', payload: 100 })},},subscriptions: {setup({dispatch, history}){history.listen(({ pathname, query }) => {if(pathToRegexp(`/y/monthCard/list`).test(pathname)) {dispatch({ type: 'query' })}},},},})
Subscriptions 表示订阅,用于订阅一个数据源,然后按需 dispatch action
select
在effects中对于param数据和当前的state数据进行再出处理,这里怎么获取state呢?采用select
select 获取到当前state中的数据
{namespace: 'list',state: {user: 'lucy'},effects: {*asyncGetUserInfo({ payload }, { call, put, select }) {// select获取当前的 stateconst user = yield select(state => {console.log(state)return state.list.user});const res = yield call(getUserInfo, { ...payload, user });if (!res.data) return;yield put({ type: 'save', payload: res });},}}
多个 effect调用
https://blog.csdn.net/tianxintiandisheng/article/details/112475583
