美文网首页
redux源码

redux源码

作者: zdxhxh | 来源:发表于2019-12-26 10:51 被阅读0次

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

    相关文章

      网友评论

          本文标题:redux源码

          本文链接:https://www.haomeiwen.com/subject/hyskoctx.html