redux阅读

createStore

function (
  reducer: Reducer,
  preloadedState?: PreloadedState | StoreEnhancer,
  enhancer?: StoreEnhancer
){
  if (
    (typeof preloadedState === 'function' && typeof enhancer === 'function') ||
    (typeof enhancer === 'function' && typeof arguments[3] === 'function')
  ) {
    throw new Error(
      'It looks like you are passing several store enhancers to ' +
        'createStore(). This is not supported. Instead, compose them ' +
        'together to a single function.'
    )
  }

  if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
    enhancer = preloadedState as StoreEnhancer
    preloadedState = undefined
  }

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

    return enhancer(createStore)(
      reducer,
      preloadedState as PreloadedState
    ) as Store, A, StateExt, Ext> & Ext
  }

  if (typeof reducer !== 'function') {
    throw new Error('Expected the reducer to be a function.')
  }
  let currentReducer = reducer
  let currentState = preloadedState as S
  let currentListeners: (() => void)[] | null = []
  let nextListeners = currentListeners
  let isDispatching = false
  function getState() {
    if (isDispatching) {
      throw new Error(
        'You may not call store.getState() while the reducer is executing. ' +
          'The reducer has already received the state as an argument. ' +
          'Pass it down from the top reducer instead of reading it from the store.'
      )
    }

    return currentState
  }
  function subscribe ...
  function dispatch...
  function replaceReducer...
  // 初始化state
  dispatch({ type: ActionTypes.REPLACE } as A)
  const store = ({
    dispatch: dispatch as Dispatch,
    subscribe,
    getState,
    replaceReducer,
    [$$observable]: observable
  }
  return store
 }

做一些不符合规则的参数,如果初始化state是函数,并且enhancer没有定义,那就认为初始化State是undefined,enchance是第二个参数。如果enhancer是个函数那不是立马调用createStore,转交给enhancer去createStore enhancer(createStore)(reducer,preloadedState as PreloadedState)

初始化state = currentState,如果调用getState()其实返回的是currentState。初始化会dispatch({ type:xx })也就是说,你可以不必传initialState这个额外的参数,只需要在reducers里面指定。type不中标的return值。

dispatch

function dispatch(action) {
      // 判断action对象
      if (!isPlainObject(action)) {
        throw new Error('Actions must be plain objects. ' + 'Use custom middleware for async actions.');
      }
      // 判断action type
      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;
        // 执行reducer
        currentState = currentReducer(currentState, action);
      } finally {
        isDispatching = false;
      }
      // 执行subscribe监听器
      // store.subscribe(() => store.getState() // state是最新的state)
      var listeners = currentListeners = nextListeners;
      for (var i = 0; i < listeners.length; i++) {
        var listener = listeners[i];
        listener();
      }
  
      return action;
    }

dispatch 触发一个action,首先,判断action是否为对象,判断action的type,其次判断isDispatching(这是一个flag,防止dispatch的reducer的时候,触发另外一个reducers,redux限制reducers同时只能触发一个)。

接下来,执行reducer函数。最后去执行subscribe监听器,注意这时候subscribe监听器可以拿到最新的state,也就是说store.subscribe(() => console.log(store.getState()) ),当前这个console是reducers改变state之后最新的值。

combineReducers

假设我们目前有combineReducers(reducer1,reducer2),如果我们要dispatch({ type: xxx }),那么reducer1,和reducer2哪个会执行?答案是:都会执行

function combineReducers(reducers) {
    var reducerKeys = Object.keys(reducers);
    var finalReducers = {};
  
    for (var i = 0; i < reducerKeys.length; i++) {
      var key = reducerKeys[i];
  
      {
        if (typeof reducers[key] === 'undefined') {
          warning("No reducer provided for key \"" + key + "\"");
        }
      }
  
      if (typeof reducers[key] === 'function') {
        finalReducers[key] = reducers[key];
      }
    }
  
    var finalReducerKeys = Object.keys(finalReducers); // This is used to make sure we don't warn about the same
    // keys multiple times.
  
    var unexpectedKeyCache;
  
    {
      unexpectedKeyCache = {};
    }
  
    var shapeAssertionError;
  
    try {
      assertReducerShape(finalReducers);
    } catch (e) {
      shapeAssertionError = e;
    }
  
    return function combination....

assertReducerShape,dispatch 一个action,type为INIT和UNLNOW_ACTION,获取初始值,判断初始值不为空

image.png

getUnexpectedStateShapeWarningMessage,1 判断reducers是否存在一个及以上。 2 判断state为一个对象。 3 判断state对应的key有响应的reducers处理

function combination(state, action) {
      if (state === void 0) {
        state = {};
      }
  
      if (shapeAssertionError) {
        throw shapeAssertionError;
      }
  
      {
        var warningMessage = getUnexpectedStateShapeWarningMessage(state, 
              finalReducers, action, unexpectedKeyCache);
  
        if (warningMessage) {
          warning(warningMessage);
        }
      }
  
      var hasChanged = false;
      var nextState = {};
  
      for (var _i = 0; _i < finalReducerKeys.length; _i++) {
        var _key = finalReducerKeys[_i];
        var reducer = finalReducers[_key];
        var previousStateForKey = state[_key];
        var nextStateForKey = reducer(previousStateForKey, action);
  
        if (typeof nextStateForKey === 'undefined') {
          var errorMessage = getUndefinedStateErrorMessage(_key, action);
          throw new Error(errorMessage);
        }
  
        nextState[_key] = nextStateForKey;
        hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
      }
  
      hasChanged = hasChanged || finalReducerKeys.length !== Object.keys(state).length;
      return hasChanged ? nextState : state;
 };

combinationcombineReducers最核心部分,combineReducers的返回值,首先从参数上去看就combination就是一个reducers。

当你执行一个dispatch(action)时,这个action会在每个模块reducers里面执行一次,2个重要的变量nextStateForKey(执行reducers后的state),previousStateForKey当前模块的state。
这里有一个非常重要的flag,hasChanged,hasChange初始值是false,当执行完reducers之后,会去判断对象的浅比较,如果nextStateForKeypreviousStateForKey不是同一个,则hasChange为true,返回值为更新的state即currentState = nextStateForKey。

Enhancer & Middleware

compose

export default function compose(...funcs: Function[]) {
  if (funcs.length === 0) {
    // infer the argument type so it is usable in inference down the line
    return (arg: T) => arg
  }

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

  return funcs.reduce((a, b) => (...args: any) => a(b(...args)))
}
// 看起来很绕,翻译成人话就是
function compose(...params) {
   let result = params.shift()
   params.forEach((current) => {
      let prev = result
      result = (...args) => {
        return current(prev(...args))
      }
   })
   return result
}

相当于compose(funcA, funcB, funcC) 形象为 compose(funcA(funcB(funcC())),这一层看起来还好理解,但是在Redux里面这个是非常绕的,虽然compose成了一个新的洋葱形函数,但是如果compose(funcA(funcB(funcC()))(1)(2),这样子的话是特别绕的因为新的函数compose(funcA(funcB(funcC()))执行后,返回值又是一个函数newCompose,那么这个函数再执行轨迹就是完全倒过来的。

applyMiddleware

如果我们正常写一个middleware是怎么样的:

function log({ getState, dispatch }) {
  console.log(1)
  return (next) => {
    console.log(2)
    return action => {
       console.log(action.type)
       next(action)
    }
  }
}

getState,和dispatch自然不必多说,next就是调用下一个函数。

初始化:第一次执行:初始化getState dispatch,第二次执行,初始化next的指向。等到调用action函数的时候才是dispatch真正的执行路径。

export default function applyMiddleware(
  ...middlewares: Middleware[]
): StoreEnhancer {
  return (createStore: StoreCreator) => (
    reducer: Reducer,
    ...args: any[]
  ) => {
    const store = createStore(reducer, ...args)
    let dispatch: Dispatch = () => {
      throw new Error(
        'Dispatching while constructing your middleware is not allowed. ' +
          'Other middleware would not be applied to this dispatch.'
      )
    }

    const middlewareAPI: MiddlewareAPI = {
      getState: store.getState,
      dispatch: (action, ...args) => dispatch(action, ...args)
    }
    const chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

这里分2个逻辑,一个createStore,一个是compose。createStore上述createStore函数有提到,enhancer为函数时,不直接初始化,而是丢给下面的enhancer函数。

接下来初始化middlewareAPI。把传入的middlewares合成一个chain,并且保存middlewareAPI。接着,改变dispatch的指向,dispatch变成middleware compose,真正的dispatch作为最后middleware的next传入进去。

这部分比较绕,可以看一下流程图:


readux-compose.png

顺便可以参考一下这里伪代码

以上,redux核心代码都分析完。百行代码千行文档,redux绕在他定的一些概念性的东西,只要理解了,也不难。

你可能感兴趣的:(redux阅读)