createStore源码解读
Opened this issue · 0 comments
jennyWan278 commented
createStore
作用
创建并维护整个应用唯一的sore
传参
createStore(reducer, preloadedState, enhancer)
- reducer:根据传入的reducer的函数来生成一个store
- reducer期望是函数类型,一般由combineReducer(所有reducer集合)函数执行后生成
- preloadedState:初始state
- 如果只传入了两个参数,并且第二个参数是函数类型,就将它作为enhancer。
- 如果传入三个参数,第二个参数不能是函数类型,第三个参数要是函数类型。
- enhancer:用于增强当前 store 的函数。enhancer由 applyMiddleware 函数生成。
- enhancer期望是函数类型
返回值
return {
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}
- dispatch:接受action,生成新的state,执行监听者队列中的函数,更新视图。
[注意]正在执行currentReducer函数获取currentState(currentState, action)时,不能执行下一次的dispatch。currentReduce是执行createStore函数时传入的reducer参数。传入currentState(执行createStore函数时传入的preloadedState)和action,获取最新的currentState。
* 传参:action, 必须为对象类型,action对象必须要有type属性
* 返回: action
- subscribe:为监听者队列传入函数,执行一次只能传入一个函数,返回一个函数。
- 传参:listener,必须为函数类型
- 返回值: 一个可执行函数,执行就能将这次传入的函数从监听者队列中移除。
- getState:获取当前store的值
- 不需要传参
- 返回值:currentState
- replaceReducer:替换reduceer
- 传参: nextReducer,必须为函数类型
- 返回值: 无返回值,会通过 currentReducer = nextReduce; dispatch({ type: ActionTypes.REPLACE })新生成state。
核心代码解析
export default function createStore(reducer, preloadedState, enhancer) {
// 如果传入了三个参数,enhancer不为函数类型,则报错提示期望enhancer是个函数类型
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
// 如果传入的enhancer为函数类型,则执行
return enhancer(createStore)(reducer, preloadedState) // 相当于执行applyMiddleware函数
// 对store.dispatch方法进行了改造,在发出 Action 和执行 Reducer 这两步之间,添加了其他功能。
}
// 将传入的reducer缓存到currentReducer变量中
let currentReducer = reducer
// 将传入的preloadedState缓存到currentState变量中
let currentState = preloadedState
// 当前监听队列赋值为空数组
let currentListeners = []
// 将当前舰艇队的值赋给下一个监听队列
let nextListeners = currentListeners
// 定义一个是否在dispatch的标识位
let isDispatching = false
/**
* 如果isDispatching为true,表示reducer正在执行。不能调用store.getState(). 因为在reducer正在执行的时候,还没有获得最新的currentState.
* 否则返回当前状态
*/
function getState() {
if (isDispatching) {
throw new Error(...)
}
return currentState
}
// 往监听队列里面去添加监听函数。监听队列里面的函数会在调用dispatch时执行
// 调用一次subscribe只能传入一个监听函数,返回一个可执行函数,执行后可以将传入的函数从监听者队列中移除。
function subscribe(listener) {
// isDispatching为true,表示正在执行reducer函数,此时不能调用store.subscribe()
if (isDispatching) {
throw new Error()
}
// 声明一个变量来标记是否已经subscribed,通过闭包的形式被缓存
let isSubscribed = true
// 如果当前监听者队列与下一次监听者队列相等,将当前监听队列浅拷贝给下一次监听队列
ensureCanMutateNextListeners()
// 把当前传入的监听函数push到下一个监听队列中,改变nextListeners就相当于改变currentListeners
nextListeners.push(listener)
// 返回解除订阅的函数
return function unsubscribe() {
// 如果没有订阅,直接返回
if (!isSubscribed) {
return
}
// 当reducer正在执行的时候不能解除队列
if (isDispatching) {
throw new Error(....)
}
// 订阅标识设置为false
isSubscribed = false
// 将当前监听队列浅拷贝赋值给下一个监听队列
ensureCanMutateNextListeners()
// 从下一个监听队列中找到当前监听器,并从队列中删除
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
}
}
// redux中通过dispatch一个action,来触发对store中的state的修改
// 参数就是一个action对象
function dispatch(action) {
// 如果reducer正在执行,则抛出错误
if (isDispatching) {
throw new Error('......')
}
try {
// 设置isDispatching为true,表示reducer函数正在执行
isDispatching = true
// 利用传入的reducer函数处理state和action,返回新的state
// 修改原有的currentState
currentState = currentReducer(currentState, action)
} finally {
// reducer函数执行完成,设置isDispatching为false
isDispatching = false
}
// 每次dispatch结束之后,就执行监听队列中的监听函数
// 将nextListeners赋值给currentListeners,保证下一次执行ensureCanMutateNextListeners方法的时候会重新拷贝一个新的副本
const listeners = (currentListeners = nextListeners)
// 循环监听器队列,执行每一个监听器,更新视图
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
// 最后返回action
return action
}
// 替换reducer
function replaceReducer(nextReducer) {
// 将nextReducer赋给缓存reducer的变量currentReducer,达到替换reducer的效果
currentReducer = nextReducer
// dispatch一个replace动作
dispatch({ type: ActionTypes.REPLACE })
}
// dispatch一个初始化的action,生成一个初始化的store.
dispatch({ type: ActionTypes.INIT })
// 最后返回这个store的所有功能
return {
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}
}
整体代码解析
export default function createStore(reducer, preloadedState, enhancer) {
// 如果createStore的第二,第三个参数都为函数类型,或者第第三,第四个参数都为函数类型
// 则提示你传了好几个enhancers给createStore是不支持的,可以将它们组合成一个函数传入
if (
(typeof preloadedState === 'function' && typeof enhancer === 'function') ||
(typeof enhancer === 'function' && typeof arguments[3] === 'function')
) {
throw new Error(
。。。。。。
)
}
// 如果只传了两个参数,且第二个参数为函数类型
// 则把preloadedState赋给enhancer,preloadedState设置为undefined
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState
preloadedState = undefined
}
// 如果传入了三个参数,enhancer不为函数类型,则报错提示期望enhancer是个函数类型
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
// 如果传入的enhancer为函数类型,则执行
return enhancer(createStore)(reducer, preloadedState) // 相当于执行applyMiddleware函数
// 对store.dispatch方法进行了改造,在发出 Action 和执行 Reducer 这两步之间,添加了其他功能。
}
// reducer不是函数类型,报错提示reducer期望是函数类型
if (typeof reducer !== 'function') {
throw new Error('Expected the reducer to be a function.')
}
// 将传入的reducer缓存到currentReducer变量中
let currentReducer = reducer
// 将传入的preloadedState缓存到currentState变量中
let currentState = preloadedState
// 当前监听队列赋值为空数组
let currentListeners = []
// 将当前舰艇队的值赋给下一个监听队列
let nextListeners = currentListeners
// 定义一个是否在dispatch的标识位
let isDispatching = false
// dispatch:分发派发
// shallow copy:浅拷贝
// 如果下一次监听队列的值等于当前监听队列,对当前队列进行浅拷贝赋值给下一个监听队列
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice() // 执行后,nextListeners不等于currentListeners
}
}
/**
* 如果isDispatching为true,表示reducer正在执行。不能调用store.getState(). 因为在reducer正在执行的时候,还没有获得最新的currentState.
* 否则返回当前状态
*/
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
}
// 往监听队列里面去添加监听函数。监听队列里面的函数会在调用dispatch时执行
// 调用一次subscribe只能传入一个监听函数,返回一个可执行函数,执行后可以将传入的函数从监听者队列中移除。
function subscribe(listener) {
// listener不是函数抛出错误
if (typeof listener !== 'function') {
throw new Error('Expected the listener to be a function.')
}
// isDispatching为true,表示正在执行reducer函数,此时不能调用store.subscribe()
if (isDispatching) {
// 在reducer执行时,您可能不会调用store.subscribe()。
// 如果您希望在更新存储后收到通知,请从组件订阅并在回调中调用store.getState()以访问最新状态。
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-reference/store#subscribe(listener) for more details.'
)
}
// 声明一个变量来标记是否已经subscribed,通过闭包的形式被缓存
let isSubscribed = true
// 如果当前监听者队列与下一次监听者队列相等,将当前监听队列浅拷贝给下一次监听队列
ensureCanMutateNextListeners()
// 把当前传入的监听函数push到下一个监听队列中,改变nextListeners就相当于改变currentListeners
nextListeners.push(listener)
// 返回解除订阅的函数
return function unsubscribe() {
// 如果没有订阅,直接返回
if (!isSubscribed) {
return
}
// 当reducer正在执行的时候不能解除队列
if (isDispatching) {
throw new Error(
'You may not unsubscribe from a store listener while the reducer is executing. ' +
'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.'
)
}
// 订阅标识设置为false
isSubscribed = false
// 将当前监听队列浅拷贝赋值给下一个监听队列
ensureCanMutateNextListeners()
// 从下一个监听队列中找到当前监听器,并从队列中删除
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
}
}
// redux中通过dispatch一个action,来触发对store中的state的修改
// 参数就是一个action对象
function dispatch(action) {
// action如果不是普通对象,则抛出错误
if (!isPlainObject(action)) {
throw new Error(
'Actions must be plain objects. ' +
'Use custom middleware for async actions.'
)
}
// 如果action对象没有type属性,则抛出错误
if (typeof action.type === 'undefined') {
throw new Error(
'Actions may not have an undefined "type" property. ' +
'Have you misspelled a constant?'
)
}
// 如果reducer正在执行,则抛出错误
// 如果上一次dispatch还没结束,则不能继续dispatch下一次
if (isDispatching) {
throw new Error('Reducers may not dispatch actions.')
}
try {
// 设置isDispatching为true,表示reducer函数正在执行
isDispatching = true
// 利用传入的reducer函数处理state和action,返回新的state
// 修改原有的currentState
currentState = currentReducer(currentState, action)
} finally {
// reducer函数执行完成,设置isDispatching为false
isDispatching = false
}
// 每次dispatch结束之后,就执行监听队列中的监听函数
// 将nextListeners赋值给currentListeners,保证下一次执行ensureCanMutateNextListeners方法的时候会重新拷贝一个新的副本
const listeners = (currentListeners = nextListeners)
// 循环监听器队列,执行每一个监听器,更新视图
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
// 最后返回action
return action
}
// 替换reducer
function replaceReducer(nextReducer) {
// nextReducer不是函数,则抛出错误
if (typeof nextReducer !== 'function') {
throw new Error('Expected the nextReducer to be a function.')
}
// 将nextReducer赋给缓存reducer的变量currentReducer,达到替换reducer的效果
currentReducer = nextReducer
// dispatch一个replace动作
dispatch({ type: ActionTypes.REPLACE })
}
// 这个函数一般来说用不到,他是配合其他特点的框架或编程**来使用的如rx.js,感兴趣的朋友可以自行学习
// 这里就不多做介绍
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 }
},
[$$observable]() {
return this
}
}
}
// dispatch一个初始化的action,生成一个初始化的store.
dispatch({ type: ActionTypes.INIT })
// 最后返回这个store的所有功能
return {
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}
}