Redux源码分析之createStore

createStore是一个高阶函数,主要作用是完成store的初始化

createStore(reducer,preloadedState,enhancer)

执行createStore完成状态初始化的时候,会在内部调用dispatch传递一个type为init的action, 并且返回一个store对象, 这也是唯一的一次非用户生成的action调度

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

  // 只传两个参数并且第二个参数是函数的情况下,将其作为增强函数enhancer, 如createStore(reducer,applyMiddleware(middleWare))
  if (typeof preloadedState === function && typeof enhancer === undefined) {
      enhancer = preloadedState
      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)
  }

  let currentReducer = reducer
  let currentState = preloadedState // 通过闭包维持一份createStore的state tree,更新时,current指针将指向dispatch生成的new state tree,  通过getStateapi对外暴露最新的state tree
  let currentListeners = []  // subscribe方法收集的订阅
  let nextListeners = currentListeners  // 用于调用ensureCanMutateNextListeners 浅拷贝一份list,防止用户在dispatching时调用subscribe/unsubscribe出现bug
  let isDispatching = false // 是否正在更新state
 
  function dispatch(action) {
    try {
      isDispatching = true
      // 改变当前状态
      currentState = currentReducer(currentState, action)
    } finally {
      isDispatching = false
    }
    // 在dispatch改变当前状态之后立即执行所有通过subscribe的函数,执行listener主要用于在更新状态之后做些什么事情,比如视图的render操作,我们可以根据最新的状态去渲染视图
    // 这种方式有一个缺点就是,不论你消费的数据有没有变化,只要你使用subscribe订阅了store,都会执行订阅函数
    // 也就是说,redux并不识别具体的订阅者,而是统一广播通知,但这一功能被react-redux实现了
    const listeners = (currentListeners = nextListeners)
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }
    return action
  }
  

  dispatch({ type: ActionTypes.INIT })
  
  return {
    dispatch,
    subscribe,
    getState,
    replaceReducer,
    [$$observable]: observable
  }
}

createStore的几个主要api

  • dispatch
  • subscribe/unsubscribe
  • getState

dispatch

负责响应用户的动作,派发action给reducer从而获取最新的视图状态

dispatch在初始化的时候由redux自身调用一次init action,其他时候都是用户由派发action调用

流程:

  1. dispatch将store的currentState指针指向reducer返回的new state
  2. 向用户广播通过subscribe注册的所有订阅
  3. 通过getState向用户暴露currentState
  function dispatch(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
  }

subscribe

store.subscribe(listener)
订阅redux 状态变化,一旦状态发生变化就执行所有的订阅函数,同时返回一个取消订阅的函数unsubscribe

  function subscribe(listener) {
    let isSubscribed = true
    nextListeners.push(listener)
    return function unsubscribe() {
      if (!isSubscribed) {
        return
      }
      isSubscribed = false
      const index = nextListeners.indexOf(listener)
      nextListeners.splice(index, 1)
      currentListeners = null
    }
  }

getState

createStore通过闭包维持一份state tree。
状态更新时, currentState指针将指向dispatch生成的new state tree, 并通过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
  }

文章标签:

原文连接:https://www.cnblogs.com/ltfxy/p/16424242.html

相关推荐