redux原理

redux 原理解析

使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
let store = createStore(counter)
store.subscribe(() => console.log(store.getState()))
store.dispatch({ type: 'INCREMENT' })

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
function createStore(reducer, preloadedState, enhancer) {
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.');
}

return enhancer(createStore)(reducer, preloadedState);
}
//***省略很多代码
function subscribe(listener) {
nextListeners.push(listener);
}
//***
function dispatch(action) {
for (var i = 0; i < listeners.length; i++) {
var listener = listeners[i];
listener();
}
return action;
}
function observable() {
var _ref;

var outerSubscribe = subscribe;
return _ref = {
subscribe: function subscribe(observer) {
if (typeof observer !== 'object' || observer === null) {
throw new TypeError('Expected the observer to be an object.');
}

function observeState() {
if (observer.next) {
observer.next(getState());
}
}

observeState();
var unsubscribe = outerSubscribe(observeState);
return {
unsubscribe: unsubscribe
};
}
}, _ref[result] = function () {
return this;
}, _ref;
}
return {
dispatch: dispatch,
subscribe: subscribe,
getState: getState,
replaceReducer: replaceReducer
}
}
  • 接受三个入参,如果传入了enhancer,那么会直接返回enhancer(createStore)(reducer, preloadedState)
  • subscribe的关键代码就是把listener加入队列
  • dispatch就是把listeners里的所有回调挨个执行
  • 其还实现了observable方法,为了就是给一些observable/reactive的库使用,是的,他们可以监听这个store的变化

中间件是怎么实现的

原理

  • applyMiddleware

    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
    function applyMiddleware() {
    for (var _len = arguments.length, middlewares = new Array(_len), _key = 0; _key < _len; _key++) {
    middlewares[_key] = arguments[_key];
    }

    return function (createStore) {
    return function () {
    var store = createStore.apply(void 0, arguments);

    var _dispatch = function dispatch() {
    throw new Error('Dispatching while constructing your middleware is not allowed. ' + 'Other middleware would not be applied to this dispatch.');
    };

    var middlewareAPI = {
    getState: store.getState,
    dispatch: function dispatch() {
    return _dispatch.apply(void 0, arguments);
    }
    };
    var chain = middlewares.map(function (middleware) {
    return middleware(middlewareAPI);
    });
    _dispatch = compose.apply(void 0, chain)(store.dispatch);
    return _objectSpread2({}, store, {
    dispatch: _dispatch
    });
    };
    };
    }
    function compose() {
    for (var _len = arguments.length, funcs = new Array(_len), _key = 0; _key < _len; _key++) {
    funcs[_key] = arguments[_key];
    }

    if (funcs.length === 0) {
    return function (arg) {
    return arg;
    };
    }

    if (funcs.length === 1) {
    return funcs[0];
    }

    return funcs.reduce(function (a, b) {
    return function () {
    return a(b.apply(void 0, arguments));
    };
    });
    }
  • 关键方法就是compose方法,把传入的middleware串联起来,并且是从右往左执行

  • applyMiddleware返回的其实是一个修改了dispatch的enhancer,入参是createStore。把初始的dispatch方法传入到compose后的middlewares,拿到处理后的dispatch替换原始store的方法。

怎么写一个middleware

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function logger({ getState }) {
return (dispatch) => (action) => {
console.log('will dispatch', action)

// 调用 middleware 链中下一个 middleware 的 dispatch。
let returnValue = dispatch(action)

console.log('state after dispatch', getState())

// 一般会是 action 本身,除非
// 后面的 middleware 修改了它。
return returnValue
}
}
  • 可见middleware是函数,返回值是一个以dispatch为入参的函数。所以applyMiddleware中要把所有middleware先执行一遍,然后再compose

redux-promise-middleware原理

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
function middleware({ dispatch } = {}) {
if (typeof dispatch === 'function') {
return createPromise()({ dispatch });
}
}
function createPromise() {
return ref => {
const { dispatch } = ref;

return next => action => {
if (action.payload) {
const PAYLOAD = action.payload;

// Step 1.1: Is the promise implicitly defined?
if (isPromise(PAYLOAD)) {
promise = PAYLOAD;
}
}
const handleReject = reason => {
const rejectedAction = getAction(reason, true);
dispatch(rejectedAction);

throw reason;
};
const handleFulfill = (value = null) => {
const resolvedAction = getAction(value, false);
dispatch(resolvedAction);

return { value, action: resolvedAction };
};
next({
type: [TYPE, PENDING].join(PROMISE_TYPE_DELIMITER),
...(data !== undefined ? { payload: data } : {}),
...(META !== undefined ? { meta: META } : {})
});
return promise.then(handleFulfill, handleReject);
}
}
}
  • 如果action.payload是一个promise的话,先dispatch一个pending状态的action,然后执行promise.then,并在其handleFulfill/handleReject中再dispatch相应的action,所以reducer中就可以根据promise的状态来写对应的处理函数