Bootstrap

【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;
;