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 } = effect
yield call(lazy) // 等待一秒钟
// effects里面 type不需要加 namespace
yield put({ type: 'counter/add', payload: 100 })
},
}
- 在Effects里,Generator函数通过yield命令将异步操作同步化,
- 无论是yield 亦或是 async 目的只有一个: 让异步编写跟同步一样 ,从而能够很好的控制执行流程
- *query(action, {call, put, select}){}表示一个worker Saga,监听所有的query action, 并触发一个ApI 调用以获取服务器数据
yield
saga使用了 Generator迭代器,解决异步回调地狱,做到了异步代码以同步书写
// 延迟执行,ms
const lazy = (time = 1000) =>
new Promise(resolve => setTimeout(() => resolve(true), time))
app.model({
namespace: 'counter',
state: { number: 0 },
// 同步的方法
reducers: {
// state是之前的状态,return返回值是新状态 state
add(state, action) {
return { number: state.number + (action.payload || 10) }
},
},
// async异步方法
effects: {
*asyncAdd(action, effect) {
const { call, put } = effect
yield call(lazy) // 等待一秒钟
// effects里面 type不需要加 namespace
yield 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返回值是新状态 state
add(state, action) {
return { number: state.number + (action.payload || 10) }
},
},
// async异步方法
effects: {
*asyncAdd(action, effect) {
const { call, put } = effect
yield call(lazy) // 等待一秒钟
// effects里面 type不需要加 namespace
yield 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获取当前的 state
const 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