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