0%

Redux 入门教程(二):中间件与异步操作

Redux 入门教程(二):中间件与异步操作

headerImage

一个关键问题没有解决:异步操作怎么办?Action 发出后,Reducer 立即算出 State,这叫做同步;Action 发出以后,过一段时间再执行 Reducer,这就是异步。

怎么才能让 Reducer 在异步操作结束后自动执行呢?这就要用到新的工具:中间件(middleware)。

middlewares

一、中间件的概念

为了理解中间件,让我们站在框架作者的角度思考问题:如果要添加功能,你会在哪个环节添加?

  1. Reducer:纯函数,只承担计算 State 的功能,不适合承担其他功能,也承担不了,因为理论上,纯函数不能进行读写操作。
  2. View:与 State 一一对应,可以看作 State 的视觉层,也不适合承担其他功能。
  3. Action:存放数据的对象,即消息的载体,只能被别人操作,自己不能进行任何操作。

想来想去,只有发送 Action 的这个步骤,即 store.dispatch() 方法,可以添加功能。

二、中间件的用法

1. 基本用法

1
2
3
4
5
6
7
8
9
import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
import createLogger from 'redux-logger';

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

2. 异步操作的基本思路

  1. 操作开始时,送出一个 Action,触发 State 更新为”正在操作”状态
  2. 操作结束后,再送出一个 Action,触发 State 更新为”操作结束”状态

三、redux-thunk 中间件

1. 安装

1
npm install --save redux-thunk

2. 使用示例

1
2
3
4
5
6
7
8
9
10
11
// Action Creator
const fetchPosts = postTitle => (dispatch, getState) => {
dispatch(requestPosts(postTitle));
return fetch(`/some-api/${postTitle}`)
.then(response => response.json())
.then(json => dispatch(receivePosts(postTitle, json)));
};
};

// 使用方法
store.dispatch(fetchPosts('reactjs'));

四、redux-saga 中间件

1. 安装

1
npm install --save redux-saga

2. 使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { takeEvery } from 'redux-saga/effects';

// Saga
function* fetchData(action) {
try {
const data = yield call(Api.fetchUser, action.payload.userId);
yield put({ type: "USER_FETCH_SUCCEEDED", user: data });
} catch (error) {
yield put({ type: "USER_FETCH_FAILED", error: error.message });
}
}

// 监听 action
function* watchFetchData() {
yield takeEvery("USER_FETCH_REQUESTED", fetchData);
}

// 配置
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
);
sagaMiddleware.run(watchFetchData);

五、总结

  1. 中间件的作用

    • 在 Action 和 Reducer 之间添加功能
    • 处理异步操作
    • 添加日志
    • 错误处理
  2. 选择中间件

    • 简单项目:redux-thunk
    • 复杂项目:redux-saga
    • 需要日志:redux-logger
  3. 最佳实践

    • 保持 Action 的简单性
    • 将复杂的异步逻辑放在中间件中
    • 使用适当的错误处理机制
    • 注意性能优化