Redux(三):中间件和异步action

一、Redux的Middlewares

① 当一个action被dispatch之前,会经过Middleware。

② 这个Middleware的作用是去截获某种特殊的类型的action,比方说Ajax请求这种类型的action,会有一个redux-thunk这样一个中间件去处理。当Middleware接收到这个action的时候,不是直接把他丢给dispatch给reducer,而是去访问一个API,当API的返回结果为true,则dispatch一个成功的action,如果为false,就dispatch一个失败的action。

③ 所以说一个Ajax请求被中间件截获之后,会先做一个预处理,预处理完成之后,他才会真正的把action给dispatch出去来更新store,这样才算完成一个Ajax请求的过程。

④ 常用的Middleware有redux-thunk和redux-saga

二、Middleware工作流程

① 截获action

Middleware可以截获某种特殊类型的action。对于Ajax请求这种类型的action,会由redux-thunk这样一个中间件去截获,他判断是否要截获的一个action的机制是判断这个action是不是一个promise,是不是一个函数。如果是一个函数就会执行它,因为这个函数内部会真正的去发一个Ajax请求。

② 发出action

处理完成之后就发出结果action

三、异步action

import axios from 'axios';
import {
    EXAMPLES_FETCH_REDDIT_LIST_BEGIN,
    EXAMPLES_FETCH_REDDIT_LIST_SUCCESS,
    EXAMPLES_FETCH_REDDIT_LIST_FAILURE,
    EXAMPLES_FETCH_REDDIT_LIST_DISMISS_ERROR,
} from './constants';

// Rekit uses redux-thunk for async actions by default: https://github.com/gaearon/redux-thunk
// If you prefer redux-saga, you can use rekit-plugin-redux-saga: https://github.com/supnate/rekit-plugin-redux-saga

//异步action
//这个是个特殊的action,返回值是一个函数。函数里面包含了几个action,这样中间件看到函数就把他给截获,等待他的promise返回
export function fetchRedditList(args = {}) {
    return dispatch => {
        // optionally you can have getState as the second argument
        dispatch({
            type: EXAMPLES_FETCH_REDDIT_LIST_BEGIN,
        });

        // Return a promise so that you could control UI flow without states in the store.
        // For example: after submit a form, you need to redirect the page to another when succeeds or show some errors message if fails.
        // It's hard to use state to manage it, but returning a promise allows you to easily achieve it.
        // e.g.: handleSubmit() { this.props.actions.submitForm(data).then(()=> {}).catch(() => {}); }
        const promise = new Promise((resolve, reject) => {
            // doRequest is a placeholder Promise. You should replace it with your own logic.
            // See the real-word example at:  https://github.com/supnate/rekit/blob/master/src/features/home/redux/fetchRedditReactjsList.js
            // args.error here is only for test coverage purpose.
            const doRequest = axios.get('http://www.reddit.com/r/reactjs.json');

            doRequest.then(
                res => {
                    dispatch({
                        type: EXAMPLES_FETCH_REDDIT_LIST_SUCCESS,
                        data: res.data,
                    });
                    resolve(res);
                },
                // Use rejectHandler as the second argument so that render errors won't be caught.
                err => {
                    dispatch({
                        type: EXAMPLES_FETCH_REDDIT_LIST_FAILURE,
                        data: { error: err },
                    });
                    reject(err);
                }
            );
        });

        return promise;
    };
}

// Async action saves request error by default, this method is used to dismiss the error info.
// If you don't want errors to be saved in Redux store, just ignore this method.
//一个同步action
export function dismissFetchRedditListError() {
    return {
        type: EXAMPLES_FETCH_REDDIT_LIST_DISMISS_ERROR,
    };
}

//reducer
export function reducer(state, action) {
    switch (action.type) {
        case EXAMPLES_FETCH_REDDIT_LIST_BEGIN:
            // Just after a request is sent
            return {
                ...state,
                fetchRedditListPending: true,
                fetchRedditListError: null,
            };

        case EXAMPLES_FETCH_REDDIT_LIST_SUCCESS:
            // The request is success
            return {
                ...state,
                redditList: action.data.data.children,

                fetchRedditListPending: false,
                fetchRedditListError: null,
            };

        case EXAMPLES_FETCH_REDDIT_LIST_FAILURE:
            // The request is failed
            return {
                ...state,
                fetchRedditListPending: false,
                fetchRedditListError: action.data.error,
            };

        case EXAMPLES_FETCH_REDDIT_LIST_DISMISS_ERROR:
            // Dismiss the request failure error
            return {
                ...state,
                fetchRedditListError: null,
            };

        default:
            return state;
    }
}

参考文档:https://redux.js.org/advanced/async-actions

参考视频:https://time.geekbang.org/course/detail/100009301-9453?utm_source=pinpaizhuanqu&utm_medium=geektime&utm_campaign=guanwang&utm_term=guanwang&utm_content=0511

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值