export default function createStore( reducer: Reducer<S, A>, preloadedState?: PreloadedState<S> | StoreEnhancer<Ext, StateExt>, enhancer?: StoreEnhancer<Ext, StateExt>): Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext { // createStore函数不支持第二三四参数为函数 // 详见https://redux.js.org/tutorials/fundamentals/part-4-store#creating-a-store-with-enhancers if ( (typeof preloadedState === 'function' && typeof enhancer === 'function') || (typeof enhancer === 'function' && typeof arguments[3] === 'function') ) { throw new Error( ... ) }
// 第二参数是函数,且第三参数不传 if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { enhancer = preloadedState as StoreEnhancer<Ext, StateExt> preloadedState = undefined }
// 有第三参数且不是函数 if (typeof enhancer !== 'undefined') { if (typeof enhancer !== 'function') { throw new Error( `Expected the enhancer to be a function. Instead, received: '${kindOf( enhancer )}'` ) }
return enhancer(createStore)( reducer, preloadedState as PreloadedState<S> ) as Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext }
// 如果reducer不是函数,要报错 if (typeof reducer !== 'function') { throw new Error( `Expected the root reducer to be a function. Instead, received: '${kindOf( reducer )}'` ) }
let currentReducer = reducer // 当前的reducer let currentState = preloadedState as S // 当前的state let currentListeners: (() => void)[] | null = [] // 事件池 let nextListeners = currentListeners let isDispatching = false // 正在派发
/** * This makes a shallow copy of currentListeners so we can use * nextListeners as a temporary list while dispatching. * * This prevents any bugs around consumers calling * subscribe/unsubscribe in the middle of a dispatch. */ function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } }
// 返回当前的state function getState(): S { if (isDispatching) { throw new Error( ... ) } return currentState as S }
//向事件池中添加更新事件 function subscribe(listener: () => void) { // 校验是不是函数 if (typeof listener !== 'function') { throw new Error( ... ) }
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/store#subscribelistener for more details.' ) }
let isSubscribed = true //避免重复添加 ensureCanMutateNextListeners() nextListeners.push(listener)
//subscribe函数每执行一次,都会返回一个unsubscribe用来从事件池中移除当前事件 return function unsubscribe() { if (!isSubscribed) { return }
if (isDispatching) { throw new Error( ... ) }
isSubscribed = false
ensureCanMutateNextListeners() // 移除当前事件 const index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) currentListeners = null } }
// 派发函数 function dispatch(action: A) { // 如果传过来的action不是对象报错 if (!isPlainObject(action)) { throw new Error( ... ) }
//每一个action中都需要一个type字段,没有就报错 if (typeof action.type === 'undefined') { throw new Error( ... ) }
//正在派发中.. if (isDispatching) { throw new Error('Reducers may not dispatch actions.') }
try { isDispatching = true // 执行reducer,改变state currentState = currentReducer(currentState, action) } finally { isDispatching = false }
// dispatch通知事件池去执行事件,遍历执行 const listeners = (currentListeners = nextListeners) for (let i = 0; i < listeners.length; i++) { const listener = listeners[i] listener() }
return action }
// 替换replaceReducer function replaceReducer<NewState, NewActions extends A>( nextReducer: Reducer<NewState, NewActions> ): Store<ExtendState<NewState, StateExt>, NewActions, StateExt, Ext> & Ext {
// 入参不是函数,报错 if (typeof nextReducer !== 'function') { throw new Error( ... ) }
... // 刚开始进来要派发一次,同步state,其中{ type: ActionTypes.REPLACE }为唯一标识 // 倘若不为唯一标识的话,那可能一开始就破坏了状态value dispatch({ type: ActionTypes.REPLACE } as A) // change the type of the store by casting it to the new store return store as unknown as Store< ExtendState<NewState, StateExt>, NewActions, StateExt, Ext > & Ext }
...
// 初始化store的时候,需要派发一次同步state dispatch({ type: ActionTypes.INIT } as A)
const store = { dispatch: dispatch as Dispatch<A>, subscribe, getState, replaceReducer, [$$observable]: observable } as unknown as Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
// 返回仓库 const store = createStore({count:0}) return store}
评论