异步数据流
严格的单向数据流是 Redux 架构的核心。这样的设计可以使应用变得更加可预测和更容易理解。所以 Redux 中的数据一般遵循以下 4 个生命周期。
- 调用
store.dispatch(action)
,启动一个 State 变更操作。 - Redux 调用传入的 Reducer 函数,返回新的 State。
- 主 Reducer 将各个子 Reducer 的输出合并为新的 State 树。
- Redux 将新的 State 树保存在 Store 中。
在默认情况下 Redux 创建的 Store 并没有使用中间件,所以只支持同步数据流。如果要使 Redux 支持异步数据流,必须加入 redux-thunk 或者 redux-promise 等中间件。这些中间件可以使 Store dispatch 除了 Action 以外的其他内容,例如函数和 Promise,从而达到实现异步数据流的目的。但是无论中间使用了那些中间件,整条中间件链中最后一次 dispatch 的 Action 一定是一个普通对象,并使用同步操作。
根据 Redux 的设计理念,Reducer、Action 等位置上都不适合使用中间件,唯一适合使用中间件的位置为store.dispatch()
。所以目前的中间件,都是对store.dispatch()
进行了改造,在发送 Action 和执行 Reducer 之间添加了其他的功能。
中间件通过 Redux 提供的applyMiddleware()
加入到 Store 中的,一般作为createStore()
方法的最后一个参数。applyMiddleware()
方法可以接受若干中间件作为参数,中间件的出现顺序代表中间件的调用顺序,并且有些中间件是存在次序要求的。
常用中间件 Redux-Thunk 可以支持 Dispatch 函数,并且可以在处理过程中多次 Dispatch。而使用 Redux-Promise 中间件则可以在 Action 中直接返回一个 Promise。
以下示例使用了 Redux-Thunk 和 Redux-Promise 中间件。
import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import reducers from './reducers';
const store = createStore(reducers, applyMiddleware(thunkMiddleware));
// 定义一个Action Creator
const fetchContents = title => (dispatch, getState) => {
dispatch(fetchContents(title));
return fetch('url')
.then(response => response.json())
.then(json =>
dispatch({
type: 'FETCH_CONTENTS',
payload: json
})
);
};
// 直接dispatch即可
store.dispatch(fetchContents('something'));
import { createStore, applyMiddleware } from 'redux';
import promiseMiddleware from 'redux-promise';
import reducers from './reducers';
const store = createStore(reducers, applyMiddleware(promiseMiddleware));
// 定义一个Action Creator
const fetchContents = (dispatch, title) =>
new Promise((resolve, reject) => {
dispatch(requestContents(title));
return fetch('url').then(response => ({
type: 'FETCH_CONTENTS',
payload: response.json()
}));
});
从以上两个示例中可以看出,无论采用哪种异步方式,最后 Dispatch 的都是非常明确的 Action,并且执行同步操作。