美文网首页
React的异步处理

React的异步处理

作者: learninginto | 来源:发表于2020-05-08 23:10 被阅读0次

React的异步处理

通常情况下,action只是一个对象,不能包含异步操作,这导致了很多创建action的逻辑只能写在组件中,代码量较多也不便于复用,同时对该部分代码测试的时候也比较困难,组件的业务逻辑也不清晰.

使用中间件了之后,可以通过actionCreator异步编写action,这样代码就会拆分到actionCreator中,可维护性大大提高,可以方便于测试、复用,同时actionCreator还集成了异步操作中不同的action派发机制,减少编码过程中的代码量

  • 解决异步action的中间件有哪些?
  1. redux-thunk
  2. redux-saga
  3. redux-promise-middleware
  4. Redux-effects
  5. Redux-side-effects
  6. Redux-loop
  7. Redux-observable

一、redux-thunk

数据加载时发送请求,使用connect将store中的属性和方法和组件进行关联,其中,mapState对应属性,mapDispatch对应方法,在这里做事件的派发,当涉及异步请求时,可以用redux-thunk。

Redux提供了一个applyMiddleware方法作为异步的中间件配置到store中。这里的中间件其实就是action与reducer之间的一个应用。

  • 安装
cnpm install redux-thunk -S
cnpm install axios
  • 原理

以前的action必须是一个扁平的对象,即使是函数时返回的也是一个对象。当使用了redux-thunk以后,它允许action返回的是一个函数dispatch,在函数中可以发送异步的请求。请求之后的数据,通过dispatch交给reducer。

  • 源码
function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => {
    return next => {
      return action => {
        if (typeof action === 'function') {
          return action(dispatch, getState, extraArgument);
        }
        return next(action);
      };
    }
  }

}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;

  • 安装http-proxy-middleware配置跨域
cnpm i http-proxy-middleware -D
  • 在src下新建setupProxy.js
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = (app) => {
    app.use(createProxyMiddleware("/ajax", {
        target: "http://m.maoyan.com",
        changeOrigin: true
    }))
}
api

以猫眼电影中影院的接口为例:

  • src / api / request.js
import api from "./index"
import axios from "axios"

export const getClassifyApi = () => axios({
    method: "get",
    url: api.category
})
  • src / api / index.js
export default {
    category: "/ajax/filterCinemas?ci=1&optimus_uuid=910E4290AC9B11E9B0072D9FF9AC7F34424DA2065D4542EA980EDC8791BBC609&optimus_risk_level=71&optimus_code=10"
}
action
  • src / action / tabTypes.js
export const classIfyType = "CLASSIFY_TYPE"
  • src / action / tabActions.js

这里的classifyAsyncAction是一个函数,并且返回一个函数,返回的函数中会有reducers给的dispatch方法。

import { classIfyType } from "./tabTypes";
import { getClassifyApi } from "../../api/request"

export const classifyAsyncAction = () => {
    //value是ajax请求之后,传递的参数
    var classifyaction = (value) => ({
        type: classIfyType,
        value
    })

    return async (dispatch, getState) => {
        //异步在这个函数里面去做的
        let data = await getClassifyApi();
        console.log(getState)
        dispatch(classifyaction(data.data));
    }
}
  • 在src / store / index.js中,通过applyMiddleware使用中间件reduxThunk
import { createStore, combineReducers, applyMiddleware } from "redux";
import tab from "./reducers/tab"
import reduxThunk from "redux-thunk"

const reducers = combineReducers({
    tab
})
const store = createStore(reducers, applyMiddleware(reduxThunk));

export default store;
  • 在src / App.js中发送dispatch验证
import React, { Component } from 'react'
import { connect } from "react-redux";
import { classIfyAsyncAction } from "./action/tab/tabActions"
class App extends Component {
  render() {
    return (
      <div></div>
    )
  }
  componentDidMount() {
    this.props.getClassifyData();
  }
}
const mapDispatchToProps = (dispatch) => ({
  getClassifyData() {
    dispatch(classifyAsyncAction())
  }
})
export default connect(null, mapDispatchToProps)(App);
  • 验证成功之后,正常在reducers中使用即可
import { classIfyType } from "../../action/tab/tabTypes"
let defaultState = {
    data: {}
}

export default (state = defaultState, actions) => {
    switch (actions.type) {
        case classIfyType:
            let dataState = JSON.parse(JSON.stringify(state));
            dataState.data = actions.value;
            return dataState;
    }
    return state;
}

二、redux-saga

redux-saga 使用了 ES6 的 Generator 功能。它允许action不返回函数,仍然是一个扁平化的对象。

git链接 官网链接

  • 安装
cnpm i redux-saga -S
  • 在store中配置
import { createStore,applyMiddleware } from "redux"
import reducer from "./reducer"
// 处理异步的文件
import mySaga from "./sagas"
import createSagaMiddleware from "redux-saga";

const sagaMiddleware = createSagaMiddleware();
const store = createStore(reducer,applyMiddleware(sagaMiddleware))
sagaMiddleware.run(mySaga);

export default store;
  • sagas.js(计数器案例)
import { put, takeEvery } from "redux-saga/effects"
import { INCREMENT } from "./actionTypes"

function asyncIncrement() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2)
        }, 2000)
    }) 
}

function* increment() {
    let result = yield asyncIncrement();
    console.log('saga increment', result);
    // 将异步查询的数据,加入到redux中
    yield put({ type: INCREMENT, data: result })
}

function* sagas() {
    // 请求数据时,加入到异步队列,加入的是action的名字
    yield takeEvery('async_increment', increment)
}

export default sagas;

相关文章

网友评论

      本文标题:React的异步处理

      本文链接:https://www.haomeiwen.com/subject/xgecnhtx.html