jennyWan278/redux

createStore源码解读

Opened this issue · 0 comments

createStore

作用

创建并维护整个应用唯一的sore

传参
createStore(reducer, preloadedState, enhancer)

  • reducer:根据传入的reducer的函数来生成一个store
    • reducer期望是函数类型,一般由combineReducer(所有reducer集合)函数执行后生成
  • preloadedState:初始state
    • 如果只传入了两个参数,并且第二个参数是函数类型,就将它作为enhancer。
    • 如果传入三个参数,第二个参数不能是函数类型,第三个参数要是函数类型。
  • enhancer:用于增强当前 store 的函数。enhancer由 applyMiddleware 函数生成。
    • enhancer期望是函数类型

返回值

return {
    dispatch,
    subscribe,
    getState,
    replaceReducer,
    [$$observable]: observable
  }
  • dispatch:接受action,生成新的state,执行监听者队列中的函数,更新视图。

[注意]正在执行currentReducer函数获取currentState(currentState, action)时,不能执行下一次的dispatch。currentReduce是执行createStore函数时传入的reducer参数。传入currentState(执行createStore函数时传入的preloadedState)和action,获取最新的currentState。

* 传参:action, 必须为对象类型,action对象必须要有type属性 
* 返回: action
  • subscribe:为监听者队列传入函数,执行一次只能传入一个函数,返回一个函数。
    • 传参:listener,必须为函数类型
    • 返回值: 一个可执行函数,执行就能将这次传入的函数从监听者队列中移除。
  • getState:获取当前store的值
    • 不需要传参
    • 返回值:currentState
  • replaceReducer:替换reduceer
    • 传参: nextReducer,必须为函数类型
    • 返回值: 无返回值,会通过 currentReducer = nextReduce; dispatch({ type: ActionTypes.REPLACE })新生成state。

核心代码解析

export default function createStore(reducer, preloadedState, enhancer) {
  // 如果传入了三个参数,enhancer不为函数类型,则报错提示期望enhancer是个函数类型
  if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.')
    }
     // 如果传入的enhancer为函数类型,则执行
    return enhancer(createStore)(reducer, preloadedState) // 相当于执行applyMiddleware函数
    // 对store.dispatch方法进行了改造,在发出 Action 和执行 Reducer 这两步之间,添加了其他功能。
  }

  // 将传入的reducer缓存到currentReducer变量中
  let currentReducer = reducer
  // 将传入的preloadedState缓存到currentState变量中
  let currentState = preloadedState
  // 当前监听队列赋值为空数组
  let currentListeners = []
  // 将当前舰艇队的值赋给下一个监听队列
  let nextListeners = currentListeners
  // 定义一个是否在dispatch的标识位
  let isDispatching = false

  /**
   * 如果isDispatching为true,表示reducer正在执行。不能调用store.getState(). 因为在reducer正在执行的时候,还没有获得最新的currentState.
   * 否则返回当前状态
   */
  function getState() {
    if (isDispatching) {
      throw new Error(...)
    }
    return currentState
  }

  // 往监听队列里面去添加监听函数。监听队列里面的函数会在调用dispatch时执行
  // 调用一次subscribe只能传入一个监听函数,返回一个可执行函数,执行后可以将传入的函数从监听者队列中移除。
  function subscribe(listener) {
    // isDispatching为true,表示正在执行reducer函数,此时不能调用store.subscribe()
    if (isDispatching) {
      throw new Error()
    }
    // 声明一个变量来标记是否已经subscribed,通过闭包的形式被缓存
    let isSubscribed = true
    // 如果当前监听者队列与下一次监听者队列相等,将当前监听队列浅拷贝给下一次监听队列
    ensureCanMutateNextListeners() 
    // 把当前传入的监听函数push到下一个监听队列中,改变nextListeners就相当于改变currentListeners
    nextListeners.push(listener)

    // 返回解除订阅的函数
    return function unsubscribe() {
      // 如果没有订阅,直接返回
      if (!isSubscribed) {
        return
      }
      // 当reducer正在执行的时候不能解除队列
      if (isDispatching) {
        throw new Error(....)
      }
      // 订阅标识设置为false
      isSubscribed = false
      // 将当前监听队列浅拷贝赋值给下一个监听队列
      ensureCanMutateNextListeners()
      // 从下一个监听队列中找到当前监听器,并从队列中删除
      const index = nextListeners.indexOf(listener)
      nextListeners.splice(index, 1)
    }
  }

  // redux中通过dispatch一个action,来触发对store中的state的修改
  // 参数就是一个action对象
  function dispatch(action) {
  
    // 如果reducer正在执行,则抛出错误
    if (isDispatching) {
      throw new Error('......')
    }

    try {
      // 设置isDispatching为true,表示reducer函数正在执行
      isDispatching = true
      // 利用传入的reducer函数处理state和action,返回新的state
      // 修改原有的currentState
      currentState = currentReducer(currentState, action)
    } finally {
      // reducer函数执行完成,设置isDispatching为false
      isDispatching = false
    }

    // 每次dispatch结束之后,就执行监听队列中的监听函数
    // 将nextListeners赋值给currentListeners,保证下一次执行ensureCanMutateNextListeners方法的时候会重新拷贝一个新的副本
    const listeners = (currentListeners = nextListeners)
    // 循环监听器队列,执行每一个监听器,更新视图
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }
    // 最后返回action
    return action
  }

  // 替换reducer
  function replaceReducer(nextReducer) {
    // 将nextReducer赋给缓存reducer的变量currentReducer,达到替换reducer的效果
    currentReducer = nextReducer

    // dispatch一个replace动作
    dispatch({ type: ActionTypes.REPLACE })
  }

  // dispatch一个初始化的action,生成一个初始化的store.
  dispatch({ type: ActionTypes.INIT })

  // 最后返回这个store的所有功能
  return {
    dispatch,
    subscribe,
    getState,
    replaceReducer,
    [$$observable]: observable
  }
}

整体代码解析

export default function createStore(reducer, preloadedState, enhancer) {
  // 如果createStore的第二,第三个参数都为函数类型,或者第第三,第四个参数都为函数类型
  // 则提示你传了好几个enhancers给createStore是不支持的,可以将它们组合成一个函数传入
  if (
    (typeof preloadedState === 'function' && typeof enhancer === 'function') ||
    (typeof enhancer === 'function' && typeof arguments[3] === 'function')
  ) {
    throw new Error(
            。。。。。。
    )
  }
  // 如果只传了两个参数,且第二个参数为函数类型
  // 则把preloadedState赋给enhancer,preloadedState设置为undefined
  if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
    enhancer = preloadedState
    preloadedState = undefined
  }
  // 如果传入了三个参数,enhancer不为函数类型,则报错提示期望enhancer是个函数类型
  if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.')
    }
     // 如果传入的enhancer为函数类型,则执行
    return enhancer(createStore)(reducer, preloadedState) // 相当于执行applyMiddleware函数
    // 对store.dispatch方法进行了改造,在发出 Action 和执行 Reducer 这两步之间,添加了其他功能。
  }

  // reducer不是函数类型,报错提示reducer期望是函数类型
  if (typeof reducer !== 'function') {
    throw new Error('Expected the reducer to be a function.')
  }

  // 将传入的reducer缓存到currentReducer变量中
  let currentReducer = reducer
  // 将传入的preloadedState缓存到currentState变量中
  let currentState = preloadedState
  // 当前监听队列赋值为空数组
  let currentListeners = []
  // 将当前舰艇队的值赋给下一个监听队列
  let nextListeners = currentListeners
  // 定义一个是否在dispatch的标识位
  let isDispatching = false


  // dispatch:分发派发
  // shallow copy:浅拷贝
  // 如果下一次监听队列的值等于当前监听队列,对当前队列进行浅拷贝赋值给下一个监听队列
  function ensureCanMutateNextListeners() {
    if (nextListeners === currentListeners) {
      nextListeners = currentListeners.slice() // 执行后,nextListeners不等于currentListeners
    }
  }

  /**
   * 如果isDispatching为true,表示reducer正在执行。不能调用store.getState(). 因为在reducer正在执行的时候,还没有获得最新的currentState.
   * 否则返回当前状态
   */
  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
  }

  // 往监听队列里面去添加监听函数。监听队列里面的函数会在调用dispatch时执行
  // 调用一次subscribe只能传入一个监听函数,返回一个可执行函数,执行后可以将传入的函数从监听者队列中移除。
  function subscribe(listener) {
    // listener不是函数抛出错误
    if (typeof listener !== 'function') {
      throw new Error('Expected the listener to be a function.')
    }
    // isDispatching为true,表示正在执行reducer函数,此时不能调用store.subscribe()
    if (isDispatching) {
      // 在reducer执行时,您可能不会调用store.subscribe()。
      // 如果您希望在更新存储后收到通知,请从组件订阅并在回调中调用store.getState()以访问最新状态。
      throw new Error(
        'You may not call store.subscribe() while the reducer is executing. ' +
          'If you would like to be notified after the store has been updated, subscribe from a ' +
          'component and invoke store.getState() in the callback to access the latest state. ' +
          'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.'
      )
    }
    // 声明一个变量来标记是否已经subscribed,通过闭包的形式被缓存
    let isSubscribed = true
    // 如果当前监听者队列与下一次监听者队列相等,将当前监听队列浅拷贝给下一次监听队列
    ensureCanMutateNextListeners() 
    // 把当前传入的监听函数push到下一个监听队列中,改变nextListeners就相当于改变currentListeners
    nextListeners.push(listener)

    // 返回解除订阅的函数
    return function unsubscribe() {
      // 如果没有订阅,直接返回
      if (!isSubscribed) {
        return
      }
      // 当reducer正在执行的时候不能解除队列
      if (isDispatching) {
        throw new Error(
          'You may not unsubscribe from a store listener while the reducer is executing. ' +
            'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.'
        )
      }
      // 订阅标识设置为false
      isSubscribed = false
      // 将当前监听队列浅拷贝赋值给下一个监听队列
      ensureCanMutateNextListeners()
      // 从下一个监听队列中找到当前监听器,并从队列中删除
      const index = nextListeners.indexOf(listener)
      nextListeners.splice(index, 1)
    }
  }

  // redux中通过dispatch一个action,来触发对store中的state的修改
  // 参数就是一个action对象
  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?'
      )
    }
    // 如果reducer正在执行,则抛出错误
    // 如果上一次dispatch还没结束,则不能继续dispatch下一次
    if (isDispatching) {
      throw new Error('Reducers may not dispatch actions.')
    }

    try {
      // 设置isDispatching为true,表示reducer函数正在执行
      isDispatching = true
      // 利用传入的reducer函数处理state和action,返回新的state
      // 修改原有的currentState
      currentState = currentReducer(currentState, action)
    } finally {
      // reducer函数执行完成,设置isDispatching为false
      isDispatching = false
    }

    // 每次dispatch结束之后,就执行监听队列中的监听函数
    // 将nextListeners赋值给currentListeners,保证下一次执行ensureCanMutateNextListeners方法的时候会重新拷贝一个新的副本
    const listeners = (currentListeners = nextListeners)
    // 循环监听器队列,执行每一个监听器,更新视图
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }
    // 最后返回action
    return action
  }

  // 替换reducer
  function replaceReducer(nextReducer) {
    // nextReducer不是函数,则抛出错误
    if (typeof nextReducer !== 'function') {
      throw new Error('Expected the nextReducer to be a function.')
    }

    // 将nextReducer赋给缓存reducer的变量currentReducer,达到替换reducer的效果
    currentReducer = nextReducer

    // dispatch一个replace动作
    dispatch({ type: ActionTypes.REPLACE })
  }

  // 这个函数一般来说用不到,他是配合其他特点的框架或编程**来使用的如rx.js,感兴趣的朋友可以自行学习
  // 这里就不多做介绍
  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 }
      },

      [$$observable]() {
        return this
      }
    }
  }

  // dispatch一个初始化的action,生成一个初始化的store.
  dispatch({ type: ActionTypes.INIT })
  // 最后返回这个store的所有功能
  return {
    dispatch,
    subscribe,
    getState,
    replaceReducer,
    [$$observable]: observable
  }
}