什么是redux-saga
redux-saga 是一个用于管理 Redux 应用异步操作的中间件(又称异步 action)。 redux-saga 通过创建 Sagas 将所有的异步操作逻辑收集在一个地方集中处理,可以用来代替 redux-thunk 中间件。
这意味着应用的逻辑会存在两个地方:
- Reducers 负责处理 action 的 state 更新
- Sagas 负责协调那些复杂或异步的操作
Sagas是通过Generator函数来创建的,如果有不熟悉 Generator函数使用的,请查看阮老师对Generator的介绍
Sagas 不同于thunks,thunks 是在action被创建时调用,而 Sagas只会在应用启动时调用(但初始启动的 Sagas 可能会动态调用其他 Sagas),Sagas 可以被看作是在后台运行的进程,Sagas 监听发起的action,然后决定基于这个 action来做什么:是发起一个异步调用(比如一个 fetch 请求),还是发起其他的action到Store,甚至是调用其他的 Sagas
在 redux-saga 的世界里,所有的任务都通用 yield Effects 来完成(Effect 可以看作是 redux-saga 的任务单元)。Effects 都是简单的 Javascript 对象,包含了要被 Saga middleware 执行的信息(打个比方,你可以看到 Redux action其实是一个个包含执行信息的对象), redux-saga 为各项任务提供了各种Effect创建器,比如调用一个异步函数,发起一个action到Store,启动一个后台任务或者等待一个满足某些条件的未来的 action
第一步骤:安装中间件
npm install --save redux-saga //yarn add redux-saga也是可以的
根据官网提供的main.js去改变项目中store.js文件
store.js
import {createStore, applyMiddleware, compose} from 'redux';
// import thunk from 'redux-thunk';
import createSagaMiddleware from 'redux-saga';
import todoSagas from './sagas'
import reducer from './reducer';
const sagaMiddleware = createSagaMiddleware()
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(applyMiddleware(sagaMiddleware));
const store = createStore(
reducer,
enhancer
);
sagaMiddleware.run(todoSagas)
export default store;
此时此刻我们发现store.js中多了一句话:sagaMiddleware.run(todoSagas),todoSagas是从sagas中引过来的,具体思路是什么呢?
就是我们需要建立一个sagas.js文件,可以专门来存放异步请求,然后在store.js中需要调用saga中间件的run的方法去运行起来
好的,下面开始走下面的流程
第二步骤:在同一管理action的地方定义新的action变量
actionCreator.js
//getInitList函数返回一个对象,对象中有一个type类型
export const getInitList = () => ({
type : GET_INIT_LIST
})
第三步骤:在需要请求的地方建立action,同时通过dispatch传递给store
demo.js
componentDidMount(){
const action = getInitList()
console.log(action)
store.dispatch(action)
}
第四步骤:此时此刻,sagas.js开始起作用了,相当于除了reducer.js能够监听到action,而sagas.js同样也能监听到状态
sagas.js
import { takeEvery,put } from 'redux-saga/effects'
import { GET_INIT_LIST } from './actionTypes'
import {initListAction} from './actionCreators'
import axios from 'axios'
function* getInitList(){
try{
const res = yield axios.get("https://www.easy-mock.com/mock/5c4173448ff5e33c8a22766e/example/listdata")
const action = initListAction(res.data.result)
yield put(action)
}catch(e){
console.log('网络请求失败')
}
}
// generator 函数
function* mySaga() {
yield takeEvery(GET_INIT_LIST, getInitList);
}
export default mySaga;
其中takeEvery是redux-saga的方法,目的是监听到action,而put的作用相当于dispatch的作用,将action传给store