学习 redux 的过程中了解到处理异步也需要在 dispatch 之前,就像 vuex 的 mutations 和 actions 一样,所以到底是谁借鉴谁啊 😂

因为 dispatch 一执行就会立马执行 reducer ,而 redux 是不能在 reducer 里产生异步的,也就意味着异步操作一定要在 reducer 触发前执行完,像 vuex 通过 actions 处理完异步再执行 mutaions 一样,我们也需要一个 actions 来做事,所以就需要中间件登场了

其中 redux-thunk 应该是用的最多的了,还有一个 redux-saga 听说更高级但是上手门槛也比较高,两个 npm 下载量不是一个等级,所以先由简入繁从 redux-thunk 上手

因为执行实际的关系,当我们触发 dispatch 的时候会先经过中间件的增强然后 next 到 reducer,所以我搂了一眼 redux-thunk 的源码,大概了解了基本实现,以下是我自己手写的一个简版 redux-thunk 的源码

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
27
28
29
30
31
32
import { legacy_createStore, applyMiddleware } from "redux"
import { reducer } from "./reducers"

// 简版 redux-thunk 的源码
const thunkMiddleware = config => store => next => action => {
// config 是 thunkMiddleware 的配置对象 key 值
// store 是 redux 的 store 对象,但是只有 getState 和 dispatch 方法
// next 是 redux 的 dispatch 方法,洋葱模型
// action 是 dispatch 的参数,action 对象

// 类型筛选,只有传过来的 action.type 和 thunkMiddleware 的配置对象 key 值相等才会执行
const matchAsyncRender = config[action.type]
if (matchAsyncRender) matchAsyncRender(store.dispatch)

// 在上面处理好了异步渲染的逻辑,然后再执行 dispatch
next(action)
}

// thunk 的使用
export const store = legacy_createStore(
reducer,
applyMiddleware(
thunkMiddleware({
async_increment: dispatch => {
setTimeout(() => {
console.log("数据dispatch来了", dispatch)
dispatch({ type: "INCREMENT" })
}, 2000)
},
})
)
)