主要通过applyMiddleware函数,借助redux中间件来处理,即通过中间件模式将原始dispatch函数进行封装处理,形成洋葱模型,将原始dispatch函数作为参数传递,在处理异步事件时,再调用原始dispatch函数修改数据状态。
redux中的异步处理流程通常如下:
- 在异步操作开始前,发送action,用来表示要发起异步操作,用户界面应该有所提示
- 在异步操作结束后,发送action,用来表示异步操作结束,根据异步操作的结果,对store中的数据和用户界面进行更新
redux中通常使用中间件来进行异步处理,常用的中间件包括 redux-thunk 或 redux-saga。
redux-thunk 使用高阶函数实现, 判别action的类型,如果action是函数,就调用这个函数,书写较为简单 。
-
使用redux-thunk
- 安装: npm install redux-thunk
- 创建store时使用 applyMiddleware 开启thunk中间件
- 使action可以返回函数, 使用dispatch提交action
// 异步 action const action = () => dispatch => ( Promise.then(res => dispatch('同步action')) )
-
redux-saga
- 创建 generator 函数,使用 takeEvery 接收异步 action
- 异步操作处理完成之后,在使用 put 触发同步 action
redux-saga的语义更清晰,耦合更宽松,易于维护和测试,所以复杂项目通常会选用redux-saga来进行异步处理。redux-saga 使用generator函数实现,集中处理了所有的异步操作,异步接口部分一目了然,但是书写较为复杂。在组件中提交的action的type,对应在saga中要处理的type,saga中处理完后,再put提交对应在reducer中的type。
// saga可以处理同步和异步
// saga就是内部yield调用了take等监听的Generator函数||yield调用了其他内部有take等监听的Generator函数
import {
call, put } from 'redux-saga/effects'
import {
takeEvery } from 'redux-saga'
function* fetchData(action) {
try {
const data = yield call(Api.fetchUser, action.payload.url);
yield put({
type: "FETCH_SUCCEEDED", data});
} catch (error) {
yield put({
type: "FETCH_FAILED", error});
}
}
export function* watchFetchData() {
yield* takeEvery('FETCH_REQUESTED', fetchData)
}