redux源码

2019-12-26  本文已影响0人  zdxhxh

createStroe.js

import ActionTypes from './utils/actionTypes'
export default function createStore(reducer,preLoadState,enhancer) { 

  if(typeof preLoadState === 'function' && typeof enhancer === 'undefined') {
    enhancer = preLoadState
    preLoadState = undefined
  }
  if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.')
    }
    return enhancer(createStore)(reducer, preLoadState)
  }

  let isDispatching = false 
  let currentReducer = reducer
  let currentState = preLoadState
  let currentListeners = []
  let nextListeners = currentListeners

  /**
   * 获取状态树方法
   */
  function getState() { 
    if(isDispatching) { 
      throw new Error('你不能此时获取state,因为现在正在派发action')
    }
    return currentState
  }

  /**
   * 订阅方法,用于监听store的改变
   * 常在更新视图UI的场景中使用
   * @param {function} listener 回调函数
   */
  function subscribe(listener) { 
    let isSubscribed = true
    // 将订阅函数存到缓存中
    nextListeners.push(listener)
    // 返回一个取消订阅的函数
    return function unsubscribe() { 
      if(!isSubscribed) { 
        return 
      }
      if(isDispatching) { 
        throw new Error('你可能在派发action的时候取消store的定语')
      }
      isSubscribed = false 
      // 可以直接通过indexOf进行函数的查找
      const index = nextListeners.indexOf(listener)
      // 删除缓存中的订阅函数
      nextListeners.splice(index, 1)
    }
  }

  /**
   * 调度任务函数
   * @param {object} action 动作对象 type + payload 
   */
  function dispatch(action) { 
    if(typeof action !== 'object' || action === null) { 
      throw new Error(
        'action对象必须是一个对象,如果想要使用异步action,请加载中间件'
      )
    }
    if(typeof action.type === 'undefined') { 
      throw new Error('action对象的type不能为空')
    }
    if(isDispatching) { 
      throw new Error('归并函数可能没有调度action')
    }
    try { 
      isDispatching = true 
      // 使用reducer 处理传入的action
      currentState = currentReducer(currentState,action)
    } finally { 
      isDispatching = false 
    }
    currentListeners = nextListeners
    const listeners = currentListeners
    let index = -1 
    // 遍历订阅的接口
    while(++index<listeners.length) { 
      const listener = listeners[index]
      listener()
    }
    return action
  }

  /**
   * 用于替换store的reducer接口
   * @param {Function} nextReducer 
   */
  function replaceReducer(nextReducer) { 
    if (typeof nextReducer !== 'function') {
      throw new Error('reducer必须是一个函数')
    }
    currentReducer = nextReducer
    // 这里调度了action ,估计是想告诉控制台,此时替换了reducer
    dispatch({ type: ActionTypes.REPLACE })
  }

  /**
   * 这个方法用于reactive的库 如rxjs 
   */
  function observable() { 
    const outerSubscribe = subscribe
    return { 
      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()
        const unsubscribe = outerSubscribe(observeState)
        return { unsubscribe }
      },
      [Symbol('observable')]() {
        return this
      }
    }
  }

  // 告诉控制台,初始化了 顺便触发reducer的default,拿到initialState
  dispatch({ type: ActionTypes.INIT })
  return { 
    dispatch,
    subscribe,
    getState,
    replaceReducer,
    [Symbol('observable')]: observable
  }
}

applyMiddleware


export 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)))
}


export default function applyMiddleware(...middlewares) {
  // 返回一个接受 createStore的函数 
  return createStore => (...args) => {
    // 创建一个store
    const store = createStore(...args)
    let dispatch = () => {
      throw new Error(
        `Dispatching while constructing your middleware is not allowed. ` +
          `Other middleware would not be applied to this dispatch.`
      )
    }
    const middlewareAPI = {
      getState: store.getState,
      dispatch: (...args) => dispatch(...args)
    }
    // 遍历执行中间件
    const chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)
    return {
      ...store,
      // 覆盖原有store的dispatch
      dispatch
    }
  }
}

combineReducers

import ActionTypes from './utils/actionTypes'


/**
 * 用于测试reducer方法,看它们是否返回初始状态
 * @param {function[]} reducers 函数reducers对象
 */
function assertReducerShape(reducers) {
  Object.keys(reducers).forEach(key => {
    const reducer = reducers[key]
    const initialState = reducer(undefined, { type: ActionTypes.INIT })

    if (typeof initialState === 'undefined') {
      throw new Error(
        `key为${key}的reducer函数没有返回一个initialState,或者这个initialState未定义`
      )
    }

    if (
      typeof reducer(undefined, {
        type: ActionTypes.PROBE_UNKNOWN_ACTION()
      }) === 'undefined'
    ) {
      throw new Error(
        `Reducer "${key}"当尝试触发一个任意action时,你的reducer返回undefined ` +
        `不要尝试处理 ${
        ActionTypes.INIT
        } 或者某些以 "redux/*"命名空间开头的action` +
        `他们是私有的,你必须返回一个值 ` +
        `current state for any unknown actions, unless it is undefined, ` +
        `in which case you must return the initial state, regardless of the ` +
        `action type. The initial state may not be undefined, but can be null.`
      )
    }
  })
}

function getUnexpectedStateShapeWarningMessage(
  inputState,
  reducers,
  action,
  unexpectedKeyCache
) {
  const reducerKeys = Object.keys(reducers)
  const argumentName =
    action && action.type === ActionTypes.INIT
      ? 'preloadedState argument passed to createStore'
      : 'previous state received by the reducer'

  if (reducerKeys.length === 0) {
    return (
      'Store中没有有效的reducers 请检查' +
      '是否combineRecducers中是否有reducers传入'
    )
  }

  if (!isPlainObject(inputState)) {
    return (
      `The ${argumentName} has unexpected type of "` +
      {}.toString.call(inputState).match(/\s([a-z|A-Z]+)/)[1] +
      `". Expected argument to be an object with the following ` +
      `keys: "${reducerKeys.join('", "')}"`
    )
  }

  const unexpectedKeys = Object.keys(inputState).filter(
    key => !reducers.hasOwnProperty(key) && !unexpectedKeyCache[key]
  )

  unexpectedKeys.forEach(key => {
    unexpectedKeyCache[key] = true
  })

  if (action && action.type === ActionTypes.REPLACE) return

  if (unexpectedKeys.length > 0) {
    return (
      `Unexpected ${unexpectedKeys.length > 1 ? 'keys' : 'key'} ` +
      `"${unexpectedKeys.join('", "')}" found in ${argumentName}. ` +
      `Expected to find one of the known reducer keys instead: ` +
      `"${reducerKeys.join('", "')}". Unexpected keys will be ignored.`
    )
  }
}


/**
 * 通过一个对象作为字典结构,传入多个reducer,并组合起来
 * @param {object} reducers 对象
 */
export default function combineReducers(reducers) {
  // 获取字典的键值
  const reducerKeys = Object.keys(reducers)
  // 函数reducers集合
  const finalReducers = {}
  for (let i = 0; i < reducerKeys.length; i++) {
    const key = reducerKeys[i]
    if (process.env.NODE_ENV !== 'production') {
      // 在开发环境,如果检测到你的reducers[key]未定义,则报警告
      if (typeof reducers[key] === 'undefined') {
        console.log((`No reducer provided for key "${key}"`))
      }
    }
    // 如果发现reducers是一个函数,则存入finalReducers中
    if (typeof reducers[key] === 'function') {
      finalReducers[key] = reducers[key]
    }
  }
  // 获取finalReducers的键值
  const finalReducerKeys = Object.keys(finalReducers)
  let unexpectedKeyCache
  if (process.env.NODE_ENV !== 'production') {
    // 生产环境开辟一个缓存  ? 
    unexpectedKeyCache = {}
  }

  let shapeAssertionError
  try {
    // 逐个检查reducer是否返回了initialState
    assertReducerShape(finalReducers)
  } catch (e) {
    // 将捕获错误赋值给变量
    shapeAssertionError = e
  }
  // 返回一个整合reducer 每次dispatch(action) 调用
  return function combination(state = {}, action) {
    // 检查到错误直接抛出,为什么不在外面抛,而是存起来这么迂回的方法
    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 < finalReducerKeys.length;i++) { 
      const key = finalReducerKeys[i]
      const reducer = finalReducers[key]
      const previousStateForKey = state[key]
      const nextStateForKey = reducer(previousStateForKey,action)
      if(typeof nextStateForKey === 'undefined') { 
        throw new Error(`key为${key}的reducer在处理${action.type}时 返回了一个空的state`)
      }
      nextState[key] = nextStateForKey
      // 如果这个reducer返回的state的地址与原有state的地址不一样 则赋值给hasChanged
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey
    }
    console.log(hasChanged,2323232)
    return hasChanged ? nextState : state
  }
}
上一篇 下一篇

猜你喜欢

热点阅读