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