【背景】
Action 发出以后,Reducer 立即算出 State,这叫做同步。Action 发出以后,过一段时间再执行 Reducer,这就是异步。
怎么才能让 Reducer 在异步操作结束后自动执行呢?这就要用到新的工具:中间件(middleware)。
一、中间件的基本认知
实现思路:改造store.dispatch()方法。
中间件雏形:

【定义】
中间件就是一个函数,对store.dispatch方法进行了改造,在发出 Action 和执行 Reducer 这两步之间,添加了其他功能。
如上例,改造后,调用新定义的store.dispatch(action)是发出Action的动作,执行next(action)是触发reducer执行的动作。
二、中间件的用法

如上,就可以完成对store.dispatch()的功能增强,使其具备生成日志功能。
【注意】
(1)createStore方法可以接受整个应用的初始状态作为参数,那样的话,applyMiddleware就是第三个参数了。

(2)中间件的次序有讲究。

上面代码中,applyMiddleware方法的三个参数,就是三个中间件。有的中间件有次序要求,使用前要查一下文档。比如,logger就一定要放在最后,否则输出结果会不正确。
三、applyMiddleware
作用:将所有中间件组成一个数组,依次执行。
源码如下:

四、异步操作的基本思路
1.action的改变
同步操作只要发出一种 Action 即可,异步操作的差别是它要发出三种 Action。
*操作发起时的 Action
*操作成功时的 Action
*操作失败时的 Action
2.state的改变
state要反映不同的操作状态。
如下例:

3.总体思路
(1)操作开始时,送出一个 Action,触发 State 更新为"正在操作"状态,View 重新渲染
(2)操作结束后,再送出一个 Action,触发 State 更新为"操作结束"状态,View 再一次重新渲染
五、redux-thunk中间件
作用:
改造store.dispatch,使其能够接受一个函数作为参数。(默认只能接受对象,即要发送的action对象)
在异步操作中使用redux-thunk:
1.异步操作的dispatch

fetchPosts是一个Action Creator,返回一个函数。
这个函数执行后,先发出一个Action(requestPosts(postTitle)),然后进行异步操作。拿到结果后,先将结果转成 JSON 格式,然后再发出一个 Action( receivePosts(postTitle, json))。
2.注意事项
(1)fetchPosts返回了一个函数,而普通的 Action Creator 默认返回一个对象。
(2)返回的函数的参数是dispatch和getState这两个 Redux 方法,普通的 Action Creator 的参数是 Action 的内容。
(3)在返回的函数之中,先发出一个 Action(requestPosts(postTitle)),表示操作开始。
(4)异步操作结束之后,再发出一个 Action(receivePosts(postTitle, json)),表示操作结束。
总结:
异步操作的第一种解决方案就是,写出一个返回函数的 Action Creator,然后使用redux-thunk中间件改造store.dispatch。
六、redux-promise中间件
作用:
改写store.dispatch,使其可以接受 Promise 对象作为参数。
这时,Action Creator 有两种写法。写法一,返回值是一个 Promise 对象。

写法二,Action 对象的payload属性是一个 Promise 对象。这需要从redux-actions模块引入createAction方法,并且写法也要变成下面这样。

第二个dispatch方法发出的是异步 Action,只有等到操作结束,这个 Action 才会实际发出。注意,createAction的第二个参数必须是一个 Promise 对象。
【附】redux-promise源码:

#整理自http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_two_async_operations.html
网友评论