functiondispatch(action: A) { if (!isPlainObject(action)) { thrownewError( ... ) }
if (typeof action.type === 'undefined') { thrownewError( ... ) }
if (isDispatching) { thrownewError('Reducers may not dispatch actions.') } try { // start running the reducer isDispatching = true // the new state comes from current reducer with current state and action currentState = currentReducer(currentState, action) } finally { //finish running the reducer isDispatching = false } /** * we get the new listeners here and exec them * currentListeners = nextListeners will ensure if listeners subscribe * unsubscribe during the exec, the change will happen in next dispatch * */ const listeners = (currentListeners = nextListeners) for (let i = 0; i < listeners.length; i++) { const listener = listeners[i] listener() }
return action }
subscribe
subscribe has a parameter called listener as a callback function.
functionsubscribe(listener: () => void) { // listener should be a function if (typeof listener !== 'function') { thrownewError('Expected the listener to be a function.') }
if (isDispatching) { thrownewError( ... ) } //ensure not repeatly unsubscribe let isSubscribed = true /** * 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. */ ensureCanMutateNextListeners() // add linstener to nextListeners nextListeners.push(listener) // unsubscribe as a return function returnfunctionunsubscribe() { if (!isSubscribed) { return }
if (isDispatching) { thrownewError( ... ) } // mark as unsubscribe isSubscribed = false // again prevent buts when unsubscribe using a shallow copy ensureCanMutateNextListeners() // get index of the listener we want to unsubscribe const index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) currentListeners = null } }
1 2 3 4 5 6
// how to make a shallow copy of current listeners functionensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } }
getState
simple as its name, just get the state
1 2 3 4 5 6 7 8 9
functiongetState(): S{ if (isDispatching) { thrownewError( ... ) }