利用Generator特性实现异步
因为Generator。结合yield yield操作符会获取右边表达示的值返回 可以用于异步变同步操作
中间件的特性: 以前的 action -> reducers -> store
现在的 action -> middleware -> reducers -> store
注意:
reducer的type 不能和generator的名字一样。否则会出现惊喜 call generator 只能接受到返回值
redux-saga初使用
安装: yarn add redux-saga
- store.js
import { createStore, combineReducers, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import createSagaMiddleware from 'redux-saga'; // 导入创建saga的函数 import {add, deleter} from './Reducers/TodoList'; import {watch} from './Saga/saga'; // 返回一个saga中间件 const sagaMiddleware = createSagaMiddleware(); export default createStore( combineReducers({add, deleter}), applyMiddleware(sagaMiddleware) ); // saga进行监听 传入的必须是一个generator sagaMiddleware.run(watch);
- Saga/saga.js
import { call, // 调用一个函数 put, take, select, // 查询store的状态 takeEvery // 对action进行监听 } from 'redux-saga/effects'; export function* fetchData() { // 利用generator + yield 同步进行数据处理 const data = yield fetch("http://jsonplaceholder.typicode.com/posts") const res = yield data.json(); // put这个函数相当于正常的dispatch分发一个action给reducer yield put({ type: 'getList', payload: res }) } // 对dispatch过来的action 进行监听 如果监听到的action type等 takeEvery的第一个参数则触发 fetchData这个函数 export function* watch() { yield takeEvery('fetchData', fetchData); }
正常使用dispatch分发action
sagaClick = () => { this.props.dispatch({ type: 'fetchData' }); }; 首先 dispatch -> action 如果type是saga监听的那个type 则运行流程为: dispatch -> action -> watch -> fetchData -> reducer -> store 如果没有和saga的type对应上 会自己分发到reducer,和以前流程保持不变
实现效果 点击sagaClick获取数据 展示到页面上:
- saga常用API
- takeEvery("actionType", generator).
解释: 监听actionType 将action分发给generator 可以传递一个通配符*监听所有的action - takeLatest("actionType", generator)
解释: 类似防抖 只会有一个任务 会自动取消前一个任务 - take
解释: take函数可以理解成为监听未来的action 告诉middleware等待第一个action Generator会暂停 直到action匹配成功 才会执行之后的语句 也就是说take是一个阻塞的effect - fork
解释: fork和call函数类似 但是fork是非阻塞函数 不会等待执行 - put
解释: put函数相当于redux的dispatch 当put一个action后。reducer中就会计算新的state并返回 注意: put也是阻塞effect - call
解释: call函数 调用其他函数 调用的函数可以是Generator 或者是返回一个promise的简单函数 call函数页数阻塞effect - select
解释: select函数是用来指示middleware调用提供的选择器获取Store上的state 类似于redux: store.getState().
yield select(state => state.getTodoList.list) 可以通过函数返回值更改值 - all
解释: yield all([call(1), call(2)]) 相当于promise.all - race
解释: yield race({post: call(1), timeout: call(2)}) 谁先返回谁先有值 - cancel
解释: fork产生的任务 可以使用cancel取消任务