redux-saga 是 redux 一个中间件,用于解决异步问题。
sagas的3种类型
root saga 立即启动的所有sagas的唯一入口
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
const store = createStore(appReducer, applyMiddleware(...middlewares));
sagaMiddleware.run(rootSaga);
watcher saga
监听被dispatch的actions,当接收到action或者知道其被触发时,调用worker saga执行任务
export default () => (function* () {
// 在这里面进行effect 处理 (副作用的处理 一般是指异步请求)
const task = yield takeEvery(loginAction.TRIGGER, authorize);
// 监听两个type 一个是主动退出,一个是登录出错
const action = yield take([loginAction.LOG_OUT, loginAction.FAILURE]);
// 就可以手动去取消本次请求
if( action.type === loginAction.LOG_OUT) yield cancel(task);
});
worker saga
执行具体的逻辑处理,如进行异步请求,处理返回结果等
const result = yield call(loginUtils.saveLoginState, token)
简单理解 'redux-saga/effects' 中的几个关键字:fork,call, put,takeEvery,takeLatest,all
1、fork 创建一个新的进程或者线程,并发发送请求。同步执行
function* user() {
yield takeEvery('FETCH_REQUEST', fetch_user); // 监听 FETCH_REQUEST action
}
// 并发发送请求
function* fetch_user() {
const [users, todos] = [
yield fork(fetchResource, 'https://jsonplaceholder.typicode.com/users'),
yield fork(fetchResource, 'https://jsonplaceholder.typicode.com/todos')
]
}
function* fetchResource(resource) {
const data = yield call(axios.get, resource);
// 获取 call 数据,触发成功后的 action
yield put({ type: 'FETCH_SUCESS', uu: data });
}
2、call 发送 api 请求 异步执行
yield call(loginUtils, token)
3、all 跟 fork 一样,同时并发多个 action,没有顺序。 同步执行
yield all([
fork(user()),
])
4、put 发送对应的 dispatch,触发对应的 action
yield put({ type:'login',data: {} })
5、select 用户获取store中的state的数据
put方法与redux中的dispatch相对应,同样的如果我们想在中间件中获取state,那么需要使用select。select方法对应的是redux中的getState,用户获取store中的state,使用方法:
const state= yield select();
6、take 是用来监听action,返回的是监听到的action对象 暂停Generator,
匹配的action被发起时,恢复执行。take结合fork,可以实现takeEvery和takeLatest的效果
const action = yield take('login');
7、takeEvery 监听对应的 action 每一次 dispatch 都会触发;
例如:点击一个新增的按钮,2s 后触发新增动作,在2s内不断点击按钮,这时候,每一次点击,都是有效的。
yield takeEvery('FETCH_USER', fetch_user);
8、takeLatest 监听对应的 action 只会触发最后一次 dispatch;
例如:点击一个新增的按钮,2s 后触发新增动作,在2s内不断点击按钮,这时候,只有最后一次点击是有效的。
yield takeLatest('FETCH_USER', fetch_user);