// subscribe 订阅方法,它将会定义 dispatch 最后执行的 listeners 数组的内容 function subscribe(listener) { // 校验 listener 的类型 if (typeof listener !== 'function') { throw new Error('Expected the listener to be a function.') } // 禁止在 reducer 中调用 subscribe // 该变量的修改在 dispatch 中,reducer 执行前设置为 true,reducer 执行后设置为 false,保证不会在 reducer 中新增订阅 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-reference/store#subscribe(listener) for more details.' ) } // 该变量用于防止调用多次 unsubscribe 函数 let isSubscribed = true; // 确保 nextListeners 与 currentListeners 不指向同一个引用 ensureCanMutateNextListeners(); // 注册监听函数 nextListeners.push(listener);
// 定义 dispatch 方法,用于派发 action function dispatch(action) { // 校验 action 的数据格式是否合法 if (!isPlainObject(action)) { throw new Error( 'Actions must be plain objects. ' + 'Use custom middleware for async actions.' ) }
// 约束 action 中必须有 type 属性作为 action 的唯一标识 if (typeof action.type === 'undefined') { throw new Error( 'Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?' ) }
// 若当前已经位于 dispatch 的流程中,则不允许再度发起 dispatch(禁止套娃) if (isDispatching) { throw new Error('Reducers may not dispatch actions.') } try { // 执行 reducer 前,先"上锁",标记当前已经存在 dispatch 执行流程 isDispatching = true // 调用 reducer,计算新的 state currentState = currentReducer(currentState, action) } finally { // 执行结束后,把"锁"打开,允许再次进行 dispatch isDispatching = false }
// 触发订阅 const listeners = (currentListeners = nextListeners); for (let i = 0; i < listeners.length; i++) { const listener = listeners[i]; listener(); } return action; }