Redux 的几个核心函数源码

根据订阅发布设计模式看了要模仿的一个功能,看着看着坑越挖越多,涉及到了redux 。顺便尝试吃了一下 redux 的几个核心函数的源码,初生涩隐有启发并作记录。

Redux 的几个核心函数源码

combineReducers

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
function combineReducers(reducers) {
const reducerKeys = Object.keys(reducers);
const finalReducers = {};
for (let i = 0; i < reducerKeys.length; i++) {
const key = reducerKeys[i];
if (process.env.NODE_ENV !== 'production') {
if (typeof reducers[key] === 'undefined') {
warning('No reducer provided for key' ${ key });
}
}
if (typeof reducers[key] === 'function') {
finalReducers[key] = reducers[key]
}
}
const finalReducerKeys = Object.keys(finalReducers);
let unexpectedKeyCache;
if (process.env.NODE_ENV !== 'production') {
unexpectedKeyCache = {};
}
let shapeAssertionError;
try {
// 判断传入的 reducer 格式是否正确,函数作用为传入的 type 不存在时,是否会返回默认值
assertReducerShape(finalReducers)
} catch (e) {
shapeAssertionError = e;
}
return function combination(state = {}, action) {
// 如果存在不返回默认值的 reducer,抛出异常
if (shapeAssertionError) {
throw shapeAssertionError
}
// 发出警告 不影响程序执行
if (process.env.NODE_ENV !== 'production') {
const warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache);
if (warningMessage) {
warning(warningMessage)
}
}
// 记录是否发生了变化,重点
let hasChanged = false;
// 要返回的下一个状态
const nextState = {};
for (let i = 0; i < finalReducers.length; i++) {
const key = finalReducerKeys[i];
const reducer = finalReducers[key];
// 使用该函数的要求,每个 reducer 的 key 值要和当前操作的 state 的参数同名,比如传入的 card:cardReducer,那么 state 操作的参数就必须是 state.card
const previousStateForKey = state[key];
const nextStateForKey = reducer(previousStateForKey, action);
if (typeof nextStateForKey === 'undefined') {
const errorMessage = getUndefinedStateErrorMessage(key, action);
throw new Error(errorMessage);
}
// 执行了 reducer 之后的结果
nextState[key] = nextStateForKey;
// 每次执行之后的结果,再综合上一次得到的 hasChanged,得到最终的 state 是否发生了变化
hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
}
// 如果发生了变化,就要返回新的 state -> nextState
return hasChanged ? nextState : state;
}
}

bindActionCreators

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
function bindActionCreator(actionCreator, dispatch) {
return (...args) => dispatch(actionCreator(..args));
}
function bindActionCreators(actionCreators, dispatch) {
// 可以只传入一个函数作为参数,它会给这个函数的返回结果添加 dispatch 处理
if (typeof actionCreators === 'function') {
return bindActionCreator(actionCreators, dispatch);
}
if (typeof actionCreators !== 'object' || actionCreators === null) {
throw new Error(
`bindActionCreators expected an object or a function,instead received ${actionCreators === null ? 'null' : typeof actionCreators}` +
`Did you write 'import ActionCreators from' instead of 'immport * as ActionCreators from'?`);
}
const keys = Object.keys(actionCreators);
const boundActionCreators = {};
for (let i = 0; i < keys.length++; i++) {
const key = keys[i];
const actionCreator = actionCreator[key];
if (typeof actionCreator === 'function') {
boundActionCreators[key] = bindActionCreator(actionCreator, dispatch);
}
}
// 为其添加 dispatch 并返回
return boundActionCreators;
}

compose

1
2
3
4
5
6
7
8
9
function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce((a, b) => (...args) => a(b(...args)));
}

applyMiddleware

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
const store = createStore(reducer, preloadedState, enhancer);
let dispatch = store.dispatch;
// 定义一个存储中间件函数的列表
let chain = [];
const middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
// 这里看出 middleware 需要符合一个规则,接受 getState() 和 dispatch 作为参数
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch);
return {
...store, // 原来的 store 结构
dispatch // 增强过的
}
}
}

createStore(重点)

图解

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
function createStore(reducer, preloadedState, enhancer) {
// 这里操作表明,可以不传第二个参数,不传默认为 undefined
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState;
preloadedState = undefined;
}
if (typeof enhancer !== 'undefined') {
// enhancer 必须是一个函数
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function');
}
// 如果传递 enhancer,则把 createStore 作为参数传递进去,第三个参数不穿也可以,applymiddleware 中会将 createStore 执行并返回
return enhancer(createStore)(reducer, preloadedState);
}
if (typeof reducer !== 'function') {
throw new Error('Expected the reducer to be a function');
}

let currentReducer = reducer;
// 当前的state
let currentState = preloadedState;
// 当前的listeners
let currentListeners = [];
let nextListeners = currentListeners;
// 是否在分发
let isDispatching = false;

function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice(); // 浅拷贝
}
}

function getState() {
return currentState;
}

function subscribe(listener) {
if (typeof listener !== 'function') {
throw new Error('Expected listener to be a function');
}
let isSubscribed = true;
ensureCanMutateNextListeners()
nextListeners.push(listener);
return function unsubscribe() {
if (!isSubscribed) {
return
}
isSubscribed = false;
ensureCanMutateNextListeners();
const index = nextListeners.indexOf(listener);
nextListeners.splice(index, 1);
}
}
function dispatch(action) {
// action 必须是一个对象{type:'xxx'}
if (!isPlainObject(action)) {
throw new Error('Actions must be plain object,Use custom middleware for async actions');
}
// 对象必须有 type 属性(唯一确定一个 action,不能重复)
if (typeof action.type === 'undefined') {
throw new Error('Actions may not have an undefined "type" property.Have you misspelled a constant');
}
// 不能同时执行两个 dispatch
if (isDispatching) {
throw new Error('Reducers may not dispatch actions');
}
try {
isDispatching = true
//不论第一次传入currentState是否有值,都会根据第一次的reducer返回默认值
//比如首次执行createStore就会传入一个几乎不会存在于reducer的case中的类型,这样就可以返回第一次传入reducer的默认值了。
currentState = currentReducer(currentState, action)
} finally {
//放开dispatch入口
isDispatching = false
}
const listeners = currentListeners = nextListeners;
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i];
listener();
}
return action;
}

function replaceReducer(nextReducer) {
if (typeof nextReducer !== 'function') {
throw new Error('Expected the nextReducer to be a function');
}
currentReducer = nextReducer;
dispatch({ type: ActionTypes.INIT });
}
// 一个正规的 reducer 都会返回一个默认值,执行这一步 是为了返回 reducer 的默认值
dispatch({ type: ActionTypes.INIT });
return {
dispatch,
subscribe,
getState,
replaceReducer
}
}
0%