Redux Middleware

Redux Middleware
redux为我们做了很多的事情,我们都可以不用通过显示的调用dispatch函数就将我们的action传递给reducer。这在前面的demo中就可以看到。但是至此,redux一直没有解决异步的问题。试想,如果我在页面输入一段内容,然后触发了一个搜索动作,此时需要向服务端请求数据并将返回的数据展示出来。这是一个很常见的功能,但是涉及到异步请求,刚刚的demo中的方法已经不再适用了。那么redux是如何解决异步问题的呢?

没错,就是引入middleware。middleware,顾名思义就是中间件。用过express的同学对中间件应该都很熟悉。其实在redux中,middleware并不仅仅用于解决异步的问题,它还可以做很多其他的事情,比如记录日志、错误报告、路由等等。

关于redux middleware的说明在官方文档中已经有了非常清晰的说明,中文版和英文版都有,这里就不在赘述,只摘录一句话,说明如下。

It provides a third-party extension point between dispatching an action, and the moment it reaches the reducer.

这里我想说下redux middleware的具体实现,我也正是从源代码中找到了困扰我的问题的原因。
先看applyMiddleware(…middlewares)的代码:

import compose from './compose'
export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, initialState, enhancer) => {
    var store = createStore(reducer, initialState, enhancer)
    var dispatch = store.dispatch
    var chain = []
    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)
    return {
      ...store,
      dispatch
    }
  }
}  

代码很短,此处我们只关注最内层函数的实现。在创建了store以后,我们对传进来的每一个middleware进行如下处理:

    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))

处理后得到一个数组保存在chain中。之后将chain传给compose,并将store.dispatch传给返回的函数。那么在这里面做了什么呢?我们再看compose的实现:

export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  } else {
    const last = funcs[funcs.length - 1]
    const rest = funcs.slice(0, -1)
    return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
  }
}

compose中的核心动作就是将传进来的所有函数倒序(reduceRight)进行如下处理:

(composed, f) => f(composed)

我们知道Array.prototype.reduceRight是从右向左累计计算的,会将上一次的计算结果作为本次计算的输入。再看看applyMiddleware中的调用代码:

dispatch = compose(…chain)(store.dispatch)
compose函数最终返回的函数被作为了dispatch函数,结合官方文档和代码,不难得出,中间件的定义形式为:

function middleware({dispatch, getState}) {
    return function (next) {
        return function (action) {
            return next(action);
        }
    }
}

middleware = (dispatch, getState) => next => action => {
    next(action);
}

也就是说,redux的中间件是一个函数,该函数接收dispatch和getState作为参数,返回一个以dispatch为参数的函数,这个函数的返回值是接收action为参数的函数(可以看做另一个dispatch函数)。在中间件链中,以dispatch为参数的函数的返回值将作为下一个中间件(准确的说应该是返回值)的参数,下一个中间件将它的返回值接着往下一个中间件传递,最终实现了store.dispatch在中间件间的传递。

看了中间件的文档和代码之后,我算是搞明白了中间件的原理。之前一直困扰我的问题现在看来其实是概念问题(此处不提也罢),中间件只关注dispatch函数的传递,至于在传递的过程中干了什么中间件并不关心。

下面看看通过中间件,我们如何实现异步调用。这里就不得不提redux-thunk中间件了。

http://www.cnblogs.com/bingooo/p/5500108.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值