REACT-redux-saga处理异步action
Redux-saga是一个用于管理 Redux 应用异步操作的中间件(又称异步action)
安装 npm i redux-saga
1. 可执行生成器
function getData1() {
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('data1');
},1000)
})
}
function getData2() {
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('data2');
},1000)
})
}
function getData3() {
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('data3');
},1000)
})
}
function *all(){
var f1 = yield getData1();
console.log(f1)//'data1'
var f2 = yield getData2();
console.log(f2)//'data2'
var f3 = yield getData3();
console.log(f3)//'data3'
}
function run(fn){
let g = fn();
function next (data){
let result = g.next(data);
console.log('result',result)//{value:yield getData1()返回的promise对象,done:布尔值判断是否执行完}
if(result.done){
console.log('done-value',result.value)//undefined
return result.value;
}
result.value.then(res=>{
console.log('res',res)//'data1'
next(res)
})
}
next();
};
run(all)
export default {}
2. redux-saga应用
2.1 store.js
import {createStore,applyMiddleware} from 'redux';
import reducer from './reducer';
import watchSage from './saga-takeEveryjs'
import createSagaMiddleware from '@redux-saga/core';
const SagaMiddleware = createSagaMiddleware();
const store = createStore(
reducer,
applyMiddleware(SagaMiddleware)
);
SagaMiddleware.run(watchSage);//sage任务
export default store;
2.2 reducer.js
const reducer = (prevState = {list1:[],list2:[]},action) => {
let newState = {...prevState};
switch (action.type) {
case 'change-list1':
newState.list1 = action.payload;
return newState;
case 'change-list2':
newState.list2 = action.payload;
return newState;
default:
return prevState;
}
}
export default reducer;
2.3 saga-takeEvery.js
import {all,takeEvery} from 'redux-saga/effects'
import getList1 from './sage/saga1'
import getList2 from './sage/saga2'
function *watchSaga(){
// yield all([saga1(),saga2()])
yield takeEvery('get-list1',getList1);
yield takeEvery('get-list2',getList2);
}
export default watchSaga;
2.4 saga/saga1.js
import {take,fork,call,put} from 'redux-saga/effects'
//集中写到sage-takeEvery
// function *saga1(){
// while(true){
// //take 监听组件发来的action
// yield take('get-list1');
// //fork 同步执行异步处理函数
// yield fork(getList1);
// };
// };
function *getList1(){
//call 函数发异步请求
let res1 = yield call(getListAction1_1);
let res2 = yield call(getListAction1_2,res1);
//put 发出新的action到reducer
yield put({
type:'change-list1',
payload:res2
});
};
function getListAction1_1(){
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve([11,22,33]);
},1000);
});
};
function getListAction1_2(data){
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve([...data,11,22,33]);
},1000);
});
};
export default getList1;
2.5 saga/saga2.js
import {take,fork,call,put} from 'redux-saga/effects'
//集中写到sage-takeEvery
// function *saga2(){
// while(true){
// //take 监听组件发来的action
// yield take('get-list2');
// //fork 同步执行异步处理函数
// yield fork(getList2);
// };
// };
function *getList2(){
//call 函数发异步请求
let res = yield new Promise((resolve, reject) => {
setTimeout(()=>{
resolve([44,55,66]);
},1000);
});
//put 发出新的action到reducer
yield put({
type:'change-list2',
payload:res
});
};
export default getList2;
2.6 App.js
import React, { Component } from 'react'
// import './01-可执行生成器'
import store from './redux/store'
export default class App extends Component {
render() {
return (
<div>
<button onClick={()=>{
if(store.getState().list1.length === 0){
store.dispatch({
type:'get-list1'
});
}else{
console.log('列表1已缓存',store.getState().list1)
};
}}>获取列表1</button>
<button onClick={()=>{
if(store.getState().list2.length === 0){
store.dispatch({
type:'get-list2'
});
}else{
console.log('列表2已缓存',store.getState().list2)
};
}}>获取列表2</button>
</div>
)
}
}
3. 项目saga应用
import {takeEvery,call,put} from 'redux-saga/effects'
import axios from 'axios'
function *watchSaga (){
yield takeEvery('get-cinemaList',getCinemaList);
}
function *getCinemaList(){
let res = yield call(getListAction);
yield put({
type:'change-cinemaList',
payload:res
});
};
function getListAction(){//返回一个promise对象
return axios({
url:"https://m.maizuo.com/gateway?cityId=110100&ticketFlag=1&k=7406159",
method:'get',
headers:{
'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.0.4","e":"16395416565231270166529","bc":"110100"}',
'X-Host': 'mall.film-ticket.cinema.list'
}
}).then(res=>{
return res.data.data.cinemas;
})
}
export default watchSaga;