Redux技术架构简介(二)-- 异步实现

说明:对Redux不了解的同窗可先看看这篇文章Redux技术架构简介(一)html

前言

这里说的Redux异步实现,是专指Redux中的异步Action实现,而不是指应用的异步实现,由于Redux自己只支持同步action,即发送action,state当即更新;那若是我在发送一个action后,须要state过一段时间再更新呢?按正常的思路redux是没法处理这种状况的,下面就来看看异步Action是如何实现的吧!react

须要提的一点是,其实彻底能够将异步逻辑写在View中,而后在回调函数中发送action。可是若是你要配合react一块儿使用,这样作就违背了react-redux的设计思想,即UI与逻辑的分离(具体的实现能够在下一篇文章中看到),并且当存在多个异步请求时也很难将异步逻辑抽象出来,因此异步逻辑应该由Redux架构实现,这样也就必须实现发送异步action了

1. 中间件(Middleware)

为了解决上面提到的问题,咱们须要引入中间件的概念。npm

(1)时机

中间件执行的时机是在action发起以后,reducer执行以前。json


即在dispatch一个action以后,通过一系列的中间件处理过程,再进行reducer。redux

(2)原理

本质上,中间件就是对dispatch函数的改造。当执行dispatch(action)时,会先调用中间件,进行一些内部逻辑处理,如:添加日志等,以后再执行dispatch。若是要支持中间件的链式调用,必须再返回一个dispatch。
下面是中间件的简单实现:segmentfault

function logger(store) {
  // 这里的 next 必须指向前一个 middleware 返回的函数:
  const next = store.dispatch

  return function dispatchAndLog(action) {
    console.log('dispatching', action)
    let result = next(action)
    console.log('next state', store.getState())
    return result
  }
}

(3) 在Redux中应用中间件

可使用Redux的API—applyMiddleware直接使用中间件,代码以下:架构

import {applyMiddleware,createStore} from 'redux';
import {createLogger} from 'redux-logger';//log中间件
import thunk from 'redux-thunk';//将dispatch改形成能够接受函数做为参数的中间件
import indexPhotomainReducer from '../reducer/indexPhotomainReducer';

const logger = createLogger();
const store  = createStore(
        indexPhotomainReducer,
        applyMiddleware(thunk, logger)
);

因而可知,能够把applyMiddleware做为createStore的第二个参数传入,你所使用的中间件须要下载单独npm包,而后按顺序传入applyMiddleware函数中(注:中间件有顺序要求,须要看下每一个中间件的使用文档,logger通常要放在最后)。app

2. Redux异步实现

(1) Action设计

须要增长三种action异步

  • 通知异步请求发起的action
  • 异步请求成功的action
  • 异步请求失败的action

示例代码以下:ide

export const requestPostsAction = () => {
 return {
     type: REQUEST_POSTS
 };
}

export const receivePostsSuccessAction = (data) => {
 return {
     type: RECEIVE_POSTS_SUCCESS,
     data
 };
}
export const receivePostsFailureAction = (error) => {
 return {
     type: RECEIVE_POSTS_FAILURE,
     error
 };
}

返回参数彻底能够自定义。这3种action分别在请求开始前,请求成功后,请求失败后发送。
## (2) State设计
为了配合异步Action,能够在state树中增长2个属性:

  • isFetching:表示是否正在处理异步请求。
  • isValidate:表示数据的有效性,他的做用是在异步请求发送失败后,告诉View当前state的数据是过期的数据。

State属性能够凭本身喜爱随意设计。设计好后能够这样编写reducer:

let sliderReducer = function (state = initialState, action) {
    switch(action.type){
        case photomainAction.RECEIVE_POSTS_SUCCESS:
               return Object.assign({}, state, {photoData,videoData,isFetching:false,isValidate:true});
        case photomainAction.RECEIVE_POSTS_FAILURE:
               return Object.assign({}, state, {isFetching:false,isValidate:false});
        case photomainAction.REQUEST_POSTS:
               return Object.assign({}, state, {isFetching:true,isValidate:false});
        default:
            return state;
    }
}

(3) redux-thunk中间件

当设计好action和state后,咱们想要达到的效果是--能够像同步同样dispatch一个action,而不用考虑异步逻辑。
为了达到这种效果,首先面临的问题是,异步逻辑放在哪里?这里只有2个选择:action中或reducer中(store是不适合处理数据的)。因为reducer必须是一个纯函数,他不适合处理像异步请求这样存在不肯定的输出的逻辑。最后只能放在action中处理了。
这时,为了处理异步请求,action建立函数须要返回一个带有异步请求逻辑的函数,而不是一个对象了。而dispatch只能接受对象,不能接受函数做为参数,这样就面临又一个问题:如何让dispatch接受函数?
接下来就是redux-thunk中间件发挥做用的时候了,他可让dispatch接受一个函数(原理就是上一节讲的,他实际上是改写了dispatch函数),最终异步的action能够这样实现:

//定义一个action creator – fetchPosts
export const fetchPosts = () => (dispatch, getState) => {
    dispatch(requestPostsAction());
    return window.fetch("/photo/initPage").then(response=>{
            if(response.ok){
                return response.json();
            }else{
                dispatch(receivePostsFailureAction("error"));
            }
        }).then(data => {
            if(data){
                dispatch(receivePostsSuccessAction(data));
            }else{
                dispatch(receivePostsFailureAction("error"));
            }
        });
}

这样就能够像同步同样发送action了,即:

dispatch(fetchPosts());

接下来只需静静等待view的更新就好了,这样就实现了整个Redux的异步流程。

本篇到此告一段落,下一篇介绍React与Redux整合技术

参考

Redux 中文文档
Redux 入门教程-阮一峰

相关文章
相关标签/搜索