国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

redux的createStore的源碼,帶中文翻譯

tanglijun / 1383人閱讀

摘要:只有在你需要實現代碼分隔,而且需要立即加載一些的時候才可能會用到它。

import isPlainObject from "lodash/isPlainObject"
import $$observable from "symbol-observable"

/**
 * These are private action types reserved by Redux.
 * For any unknown actions, you must return the current state.
 * If the current state is undefined, you must return the initial state.
 * Do not reference these action types directly in your code.
 * 
 * 這些都是redux本身預置的私有action types 
 * 對于任何未知的action, 你一定要return當前的state.
 * 如果當前的state是undefined, 你一定要return最初始的state.
 * 一定,一定,一定不要在代碼中直接引用action types .
 */
export const ActionTypes = {  //初始化action的type,沒有action參數的時候用
  INIT: "@@redux/INIT"
}

/**
 * Creates a Redux store that holds the state tree.
 * The only way to change the data in the store is to call `dispatch()` on it.
 * There should only be a single store in your app. To specify how different
 * parts of the state tree respond to actions, you may combine several reducers
 * into a single reducer function by using `combineReducers`.
 *
 * 創建一個包含state tree(狀態樹)的redux store.
 * 唯一改變store中data(數據)的方法是調用`dispatch()`方法.
 * 在你的程序中應該只存在唯一一個store, 來表明state tree各部分怎樣對action做出反應
 * 你可能需要將多個reducer用`combineReducers`組合在一起
 * 
 * @param {Function} reducer A function that returns the next state tree, given
 * the current state tree and the action to handle.
 * 
 * @param {Function} reducer 參數reducer是一個返回下一個state tree(狀態樹)的函數,來操作當前的state和action
 *
 * @param {any} [preloadedState] The initial state. You may optionally specify it
 * to hydrate the state from the server in universal apps, or to restore a
 * previously serialized user session.
 * If you use `combineReducers` to produce the root reducer function, this must be
 * an object with the same shape as `combineReducers` keys.
 * 
 * @param {any} [preloadedState] 初始化的state,可選參數,你可以在universal(一般的,普遍的,我不知道怎么說比較合適)
 * 的程序中與服務器的state結合,或者restore一個預先連續的user session(直譯過來的,一般用不到)
 * 如果你用`combineReducers`產生一個根reducer函數,這一定是一個和`combineReducers`的key一樣的對象(根reducer是一個對象)
 *
 * @param {Function} [enhancer] The store enhancer. You may optionally specify it
 * to enhance the store with third-party capabilities such as middleware,
 * time travel, persistence, etc. The only store enhancer that ships with Redux
 * is `applyMiddleware()`.
 * 
 * @param {Function} [enhancer] store增強器. 可選參數.用來增強第三方庫的能力集(這個詞是直譯),
 * 比如中間件,時空穿越,和持續性(也是直譯).redux的store增強器是`applyMiddleware()`
 *
 * @returns {Store} A Redux store that lets you read the state, dispatch actions
 * and subscribe to changes.
 * 
 * @returns {Store} 返回值 一個redux的store,讓你可以讀取state, dispatch actions 和訂閱更改
 */

//createStore的目的只是創建一個store,這個store包含5個方法(一般只用到3個,最常用的是dispatch)
export default function createStore(reducer, preloadedState, enhancer) {
  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.")//期望enhancer是個函數
    }
    // 當enhancer是函數的時候返回,然后執行,并將createStore作為參數傳入,然后createStore就在enhancer里面
    //去執行了
    return enhancer(createStore)(reducer, preloadedState)
  }

  if (typeof reducer !== "function") {
    throw new Error("Expected the reducer to be a function.")
  }

  let currentReducer = reducer  //一般此reducer不是單個的reducer函數,而是combineReducers函數
  let currentState = preloadedState
  let currentListeners = []  //監聽函數
  let nextListeners = currentListeners
  let isDispatching = false

  function ensureCanMutateNextListeners() { //nextListeners不是currentListeners
    if (nextListeners === currentListeners) {
      nextListeners = currentListeners.slice()
    }
  }

  /**
   * Reads the state tree managed by the store.
   *
   * 讀取被store管理的state樹
   * 
   * @returns {any} The current state tree of your application.
   * 
   *返回你的程序的當前的state樹 
   */
  function getState() {
    return currentState
  }

  /**
   * Adds a change listener. It will be called any time an action is dispatched,
   * and some part of the state tree may potentially have changed. You may then
   * call `getState()` to read the current state tree inside the callback.
   *
   * 添加一個改變事件,任何時候一個action被dispatch這個事件就會被調用,然后state樹的某一部分就
   * 會改變. 你也可以在回調函數里面調用`getState()`來查看當前的state樹
   * 
   * You may call `dispatch()` from a change listener, with the following
   * caveats:
   *
   * 以下幾種情況你也可以調用`dispatch()`
   * 
   * 1. The subscriptions are snapshotted just before every `dispatch()` call.
   * If you subscribe or unsubscribe while the listeners are being invoked, this
   * will not have any effect on the `dispatch()` that is currently in progress.
   * However, the next `dispatch()` call, whether nested or not, will use a more
   * recent snapshot of the subscription list.
   *
   * 每次調用`dispatch`之前,訂閱都會被snapshot,
   * 當事件被觸發的時候你訂閱或者不訂閱,在當前的進程中都不會對`dispatch`有什么影響
   * 然而當下一次`dispatch`被調用時,無論嵌套與否,將會使用最近的訂閱列表的snapshot
   * 
   * 2. The listener should not expect to see all state changes, as the state
   * might have been updated multiple times during a nested `dispatch()` before
   * the listener is called. It is, however, guaranteed that all subscribers
   * registered before the `dispatch()` started will be called with the latest
   * state by the time it exits.
   *
   * 不要期待監聽事件可以看到所有的狀態改變,因為在事件被調用前,state在嵌套的`dispatch`間
   * 可能已經更新了很多次
   * 
   * @param {Function} listener A callback to be invoked on every dispatch.
   * 每次dispatch都會被出發的回調函數
   * 
   * @returns {Function} A function to remove this change listener.
   * 返回一個移除該事件的函數
   */
  function subscribe(listener) {
    if (typeof listener !== "function") {
      throw new Error("Expected listener to be a function.")
    }

    let isSubscribed = true

    ensureCanMutateNextListeners()
    nextListeners.push(listener) //添加事件到nextListeners數組

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

      isSubscribed = false

      ensureCanMutateNextListeners()
      const index = nextListeners.indexOf(listener)
      nextListeners.splice(index, 1) //從nextListeners數組中移除事件
    }
  }

  /**
   * Dispatches an action. It is the only way to trigger a state change.
   *
   * dispatch  action是唯一觸發state改變的途徑
   * 
   * The `reducer` function, used to create the store, will be called with the
   * current state tree and the given `action`. Its return value will
   * be considered the **next** state of the tree, and the change listeners
   * will be notified.
   *
   * `reducer`函數,被用來創建store,有當前的state樹和action就會被調用(state和action是reducer函數的參數)
   * 它的返回值會被當做下一個state樹.監聽事件會注意到state樹的改變
   * 
   * The base implementation only supports plain object actions. If you want to
   * dispatch a Promise, an Observable, a thunk, or something else, you need to
   * wrap your store creating function into the corresponding middleware. For
   * example, see the documentation for the `redux-thunk` package. Even the
   * middleware will eventually dispatch plain object actions using this method.
   *
   * 最基本的用法是僅支持 為純對象的 action,如果你想要dispatch一個promise,一個Observable,
   * thunk,或是其他東西,你需要封裝store創建一個進入到相應中間件的函數.  比如,看一個`redux-thunk`
   * 的文檔,即使是中間件最終也會用這個方法dispatch  純對象的action
   * 
   * @param {Object} action A plain object representing “what changed”. It is
   * a good idea to keep actions serializable so you can record and replay user
   * sessions, or use the time travelling `redux-devtools`. An action must have
   * a `type` property which may not be `undefined`. It is a good idea to use
   * string constants for action types.
   *
   * action是一個純對象,代表"什么被改變了". 保持action的連續性是個好主意,這樣你就可以記錄和
   * 重現user session,或者使用時空穿梭`redux-devtools`. 
   * action必須包含一個`type`屬性,即使是`undefined`. 通常使用字符串常量表示
   * 
   * @returns {Object} For convenience, the same action object you dispatched.
   *
   * 為了方便,返回你dispatch的action
   * 
   * Note that, if you use a custom middleware, it may wrap `dispatch()` to
   * return something else (for example, a Promise you can await).
   * 注意 如果你想使用特定的中間件,可封裝`dispatch`返回其他東西(比如, 一個異步調用的promise)
   * 
   */
  function dispatch(action) {
    if (!isPlainObject(action)) {
      throw new Error(
        "Actions must be plain objects. " +
        "Use custom middleware for async actions."
      )//actions必須為純對象,使用特定中間件異步調用actions
    }

    if (typeof action.type === "undefined") {
      throw new Error(
        "Actions may not have an undefined "type" property. " +
        "Have you misspelled a constant?"
      )//actions可能有一個未定義的type屬性,你可能拼錯了這個常量
    }

    if (isDispatching) {
      throw new Error("Reducers may not dispatch actions.")//reducer沒有dispatch action
    }

    try {
      isDispatching = true
      //dispatch的目的就是改變currentState
      currentState = currentReducer(currentState, action) //currentReducer = reducer
    } finally {
      isDispatching = false
    }

    const listeners = currentListeners = nextListeners  //訂閱函數的事件
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }

    return action
  }

  /**
   * Replaces the reducer currently used by the store to calculate the state.
   *
   * 替換 store 當前用來計算 state 的 reducer。
   * 
   * You might need this if your app implements code splitting and you want to
   * load some of the reducers dynamically. You might also need this if you
   * implement a hot reloading mechanism for Redux.
   *
   * 這是一個高級 API。只有在你需要實現代碼分隔,而且需要立即加載一些 reducer 的時候才可能會用到它。
   *在實現 Redux 熱加載機制的時候也可能會用到
   * 
   * @param {Function} nextReducer The reducer for the store to use instead.
   * store所替換的reducer
   * @returns {void}
   */
  function replaceReducer(nextReducer) {
    if (typeof nextReducer !== "function") {
      throw new Error("Expected the nextReducer to be a function.")
    }

    currentReducer = nextReducer
    dispatch({ type: ActionTypes.INIT })
  }

  /**
   * Interoperability point for observable/reactive libraries.
   * @returns {observable} A minimal observable of state changes.
   * For more information, see the observable proposal:
   * https://github.com/tc39/proposal-observable
   * 
   * observable/reactive庫的互用性
   * observable是一個mini的 可觀察state的改變
   * 在下面這個網址查看更多observable的信息
   */
  function observable() {
    const outerSubscribe = subscribe
    return {
      /**
       * The minimal observable subscription method.
       * @param {Object} observer Any object that can be used as an observer.
       * The observer object should have a `next` method.
       * @returns {subscription} An object with an `unsubscribe` method that can
       * be used to unsubscribe the observable from the store, and prevent further
       * emission of values from the observable.
       * 
       * mini的可觀察訂閱的方法
       * observer是 任何對象都可以用作觀察者,這個觀察者應該有一個`next`方法
       * subscription 一個有`unsubscribe`方法的對象.可以用做退訂observable,防止進一步發出value值
       * (我也不知道什么意思,外國人說話比較隨意)
       */
      subscribe(observer) {
        if (typeof observer !== "object") {
          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
      }
    }
  }

  // When a store is created, an "INIT" action is dispatched so that every
  // reducer returns their initial state. This effectively populates
  // the initial state tree.
  /** 
   * 當創建一個store的時候,一個初始的action就被dispatch了,所以每個reducer都會返回初始的state
   * 這個可以很高效的得到state樹
  */
  dispatch({ type: ActionTypes.INIT })

  return {
    dispatch,
    subscribe,
    getState,
    replaceReducer,
    [$$observable]: observable
  }
}

源碼解析請參考 https://segmentfault.com/a/11...

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102363.html

相關文章

  • reduxcombineReducers源碼,中文翻譯

    摘要:是這個函數名翻譯為獲取未定義的錯誤信息對于返回一定要很明確的返回之前的這樣就可以忽略一個如果你想這個沒有返回值你可以返回而不是獲取與預期不符的的結構警告信息聲明結構初始化時返回如果傳給的是你一定要很明確地返回初始初始可能是如果你不想給這 import { ActionTypes } from ./createStore import isPlainObject from lodash/...

    Ajian 評論0 收藏0
  • redux中applyMiddleware源碼,中文注釋

    摘要:理解需要跟結合首先來看是怎樣創建的再來看的源碼的第三個參數就是此時會返回也就是在中間件里面去執行了返回的是函數也就是函數然后又跑到里面作為第三個參數所以能把作為參數傳進去一個小例子測試返回函數后是什么東西創建一個的方法使用中間件的增強器對于 理解applyMiddleware需要跟createStore結合.首先來看createStore是怎樣創建store的. showImg(htt...

    shiweifu 評論0 收藏0
  • 重讀redux源碼(二)

    摘要:函數組合,科里化的串聯結合示例源碼,實現也很優雅,對于返回的,將等參數傳遞進去,然后執行,等待回調異步完成再。對于正常對象則進行下一步。前言 作為前端狀態管理器,這個比較跨時代的工具庫redux有很多實現和思想值得我們思考。在深入源碼之前,我們可以相關注下一些常見問題,這樣帶著問題去看實現,也能更加清晰的了解。 常見問題 大概看了下主要有這么幾個: redux三大原則 這個可以直接參考...

    dingda 評論0 收藏0
  • Redux專題:實用

    摘要:在英文中的意思是有效載荷。有一個動作被發射了顧名思義,替換,這主要是方便開發者調試用的。相同的輸入必須返回相同的輸出,而且不能對外產生副作用。怎么辦呢開發者得手動維護一個訂閱器,才能監聽到狀態變化,從而觸發頁面重新渲染。 本文是『horseshoe·Redux專題』系列文章之一,后續會有更多專題推出來我的 GitHub repo 閱讀完整的專題文章來我的 個人博客 獲得無與倫比的閱讀體...

    Big_fat_cat 評論0 收藏0
  • redux中間件探秘

    摘要:接下來我們來看看源碼中的模塊是怎么應用中間件的。如何實現中間件操作的。新的會從第一個中間件開始觸發,這樣,在我們調用的時候,就會將中間件走一遍了。函數如果存在多個中間件,直接使用方法將各個中間件嵌套起來。 從redux-thunk引出思考 在使用redux-thunk進行異步action書寫的時候,我經常好奇redux到底如何運作,讓asyncAction成為可能 為了探究,我們必須看...

    Jeff 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<