redux 源码解析之createStore

257 阅读2分钟

目录结构
image.png

工具类
actionTypes
isPlainObject
waring

createStore.js:

先看看createStore方法

export default function createStore(reducer, preloadedState, enhancer) {……}

用法举例:const store=Redux.createStore(reducers);

第一步:参数校验

期望:reducer、enhancer是一个function、preloadedState是个对象

 //一、如果preloadedState是个function或者多输了一个参数,报错
 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'
    )
  }

  //二、如果preloadedState是个function,且第三个参数enhancer未输入,则将第二个参数当作第三个参数使用
  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.')
    }

    return enhancer(createStore)(reducer, preloadedState)
  }

 //如果reducer不是个函数,报错
  if (typeof reducer !== 'function') {
    throw new Error('Expected the reducer to be a function.')
  }

怎么样,看起来是不是很简单!

第二步:变量的声明与设置

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

第三步:声明方法

   dispatch,
   subscribe,
   getState,
   replaceReducer,
   [$$observable]: observable

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?'
      )
    }
   
    //判断当前是否有执行其他的reducer操作
    if (isDispatching) {
      throw new Error('Reducers may not dispatch actions.')
    }

    //执行
    //设置isDispatching为true,防止后续的action进来触发reducer操作
    //根据action触发状态更新
    try {
      isDispatching = true
      currentState = currentReducer(currentState, action)
    } finally {
      isDispatching = false
    }

    //当前状态设置完毕后,执行监听函数
    const listeners = (currentListeners = nextListeners)
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }
   //返回参数
    return action
  }

replaceReducer

参数校验 判断参数nextReducer是不是function
触发state更新操作

  function replaceReducer(nextReducer) {
  
    if (typeof nextReducer !== 'function') {
      throw new Error('Expected the nextReducer to be a function.')
    }
    currentReducer = nextReducer
    dispatch({ type: ActionTypes.REPLACE })
  }

getState

获取当前状态

  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
  }

subscribe

 function subscribe(listener) {
 //参数校验 
    if (typeof listener !== 'function') {
      throw new Error('Expected the listener to be a function.')
    }
 //如果reducer正在执行,报错
 if (isDispatching) {
      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.'
      )
    }

    let isSubscribed = true

    ensureCanMutateNextListeners()
    nextListeners.push(listener)

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

      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.'
        )
      }

      isSubscribed = false

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