美文网首页
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