Redux - createStore源码解析

分部解释源码:

ActionTypes

export var ActionTypes = {
INIT: '@@redux/INIT'
};

这个ActionTypes的作用,INIT作为内部私有的type,也就是说我们程序不要把type命名和这个一样.
当这个type传到reducer里的时候.他的目的就是要让reducer找不到对应的type,以便返回默认的state回来.


createStore分解

基本的参数检查

if (typeof initialState === 'function' && typeof enhancer === 'undefined') {
enhancer = initialState;
initialState = undefined;
}

if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.');
}

return enhancer(createStore)(reducer, initialState);
}

if (typeof reducer !== 'function') {
throw new Error('Expected the reducer to be a function.');
}
  • 这里检查有没有initialState
  • enhancer 有没有,这个东西后面middleware的时候会说
  • reducer的类型

内部变量初始化

var currentReducer = reducer;
var currentState = initialState;
var currentListeners = [];
var nextListeners = currentListeners;
var isDispatching = false;

function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice();
}
}

/**
* Reads the state tree managed by the store.
*
* @returns {any} The current state tree of your application.
*/
function getState() {
return currentState;
}

这里的listener 其实就subscribe的那些function, 后面会dispatch的时候把这个array里的所有listener都执行,以实现通知

ensureCanMutateNextListeners 方法是为了把引用断开,两个数组可以分别操作,以便比较

getState 就是返回当前最新的state了


subscribe

function subscribe(listener) {
if (typeof listener !== 'function') {
throw new Error('Expected listener to be a function.');
}

var isSubscribed = true;

ensureCanMutateNextListeners();
nextListeners.push(listener);

return function unsubscribe() {
if (!isSubscribed) {
return;
}

isSubscribed = false;

ensureCanMutateNextListeners();
var index = nextListeners.indexOf(listener);
nextListeners.splice(index, 1);
};
}

那些subscribe store的家伙想干嘛,无非就是想当state变化的时候,能得到通知:

  • 先基本检查类型
  • 当前listeners 和nextListener分开
  • 把订阅者加入nextListener数组
  • 返回一个取消订阅的方法
    • 取消的时候 要改变状态
    • 从订阅者数据去掉这个listener

所以谁能得到通知全靠redux维护 listener数组


dispatch

function dispatch(action) {
if (!isPlainObject(action)) {
throw new Error('Actions must be plain objects. ' + 'Use custom middleware for async actions.');
}

if (typeof action.type === 'undefined') {
throw new Error('Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?');
}

if (isDispatching) {
throw new Error('Reducers may not dispatch actions.');
}

try {
isDispatching = true;
currentState = currentReducer(currentState, action);
} finally {
isDispatching = false;
}

var listeners = currentListeners = nextListeners;
for (var i = 0; i < listeners.length; i++) {
listeners[i]();
}

return action;
}

dispatch干了啥?

他接受你的action 就是 发什么了什么的数据,然后传递给reducer去改变state.
更新后,让所有订阅者得到通知消息


replaceReducer

function replaceReducer(nextReducer) {
if (typeof nextReducer !== 'function') {
throw new Error('Expected the nextReducer to be a function.');
}

currentReducer = nextReducer;
dispatch({ type: ActionTypes.INIT });
}

replaceReducer 这个方法貌似运用的几率不是很高,他目的就是动态的替换掉原先createStore时传入的reducer


observable

function observable() {
var _ref;

var outerSubscribe = subscribe;
return _ref = {
/**
* The minimal observable subscription method.
* @param {Object} observer Any object that can be used as an observer.
* The observer object should have a `next` method.
* @returns {subscription} An object with an `unsubscribe` method that can
* be used to unsubscribe the observable from the store, and prevent further
* emission of values from the observable.
*/

subscribe: function subscribe(observer) {
if (typeof observer !== 'object') {
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[$$observable] = function () {
return this;
}, _ref;
}

这个方法很特别,因为我在源码里,没有找到任何地方调用它

首先这个方法的调用是个问题,后面解释这个句话
先看看他做了什么:

  • 执行后返回了一个obj
    • 这个obj有个subscribe为key的方法
      • 这个方法接受一个observer obj
      • 他定义订阅者的会收到最新的state - 因为他把订阅者push进了listener的数组里
      • 返回一个取消订阅的方法
  • 给返回的obj加个 $$observable的字段

伪代码

var unsubscribe = store.observable().subscribe(observer)

好看到这里我们基本可以认为,这是redux 给这个观察者模式封装了一层,搞得像rxjs似的


收尾

dispatch({ type: ActionTypes.INIT });

return _ref2 = {
dispatch: dispatch,
subscribe: subscribe,
getState: getState,
replaceReducer: replaceReducer
}, _ref2[$$observable] = observable, _ref2;

这里先去获取初始state了

然后返回这个store

  • dispatch
  • subscribe
  • getState
  • replaceReducer

这个几个内部方法都暴露出去了

最后他给这个store又加了一个$$observable 字段来只想内部这个observable方法

也就是想调用observable, 你要store[$$observable]() 才行
但这个$$observable 是个Symbol生成的唯一标识,怎么调用还没搞清楚.我得去stackoverflow问问
http://stackoverflow.com/questions/36909612/how-to-understand-the-observable-function-under-createstore