Redux实现思路简介

143 阅读2分钟

Redux有3大核心,actions、store和reducer。Redux维护一个state,接受用户定义的reducer,用于根据action计算新的state,当用户触发action后,Redux调用reducer计算新的state,更新state,然后将新的state发布给订阅者。

下面讲一下redux的简单实现:createStore这个API的实现。

先来看下createStore的使用。

const defaultState = {
    // 开关默认关闭状态
    isSwitchOn: false
};
function reducer(state = defaultState, action) {
    switch (action.type) {
        case 'open':
        return {isSwitchOn: true};
        case 'close':
        return {isSwitchOn: false};
        default:
        return state;
    }
}
const store = createStore(reducer);
const unsubscribe = store.subscribe(() => {
    console.log('state', store.getState());
});
store.dispatch({type: 'open'});
unsubscribe();

我们看到createStore接收一个方法reducer作为参数,返回一个对象store,store有3个方法

  • getState,获取当前状态。
  • subscribe,接收一个回调作为参数,订阅状态改变,它返回一个函数,用来解除订阅。
  • dispatch,接收一个action对象作为参数,触发action之后会依据reducer计算新的状态,并通知订阅者。

根据上面的列举,我们用TypeScript写一个简单的redux

interface IStore {
  subscribe: (cb: Function) => void,
  getState: () => Object,
  dispatch: (action: Object) => void
}

const createStore = (reducer: Function): IStore => {
  let state = reducer();
  const listeners = [];
  const subscribe = cb => {
    listeners.push(cb);
    return () => {
        const index = listeners.indexOf(cb);
        listeners.splice(index, 1);
    };
  };
  const getState = () => state;
  const dispatch = action => {
    state = reducer(action);
    listeners.forEach(listener => listener());
  };
  
  return {
    subscribe, getState, dispatch
  };
};

但是在这个简单的实现中有几个问题没有考虑到:

  1. reducer应该是一个纯函数,但是用户如果在reducer中调用getState、subscribe、dispatch怎么办?
  2. 如果用户连续调用解绑函数怎么办?
  3. 如果用户在dispatch过程中,即在订阅者中做绑定和解绑的操作怎么办?

对于上面的问题,redux的解决方案是这样的:

  1. 设置标志位:isDispatching,用reducer计算新state时候置为true,在计算完再置为false。然后在getState、subscribe、dispatch方法中判断,如果isDispatching为true,则抛出错误。
  2. 设置标志位:isSubscribed,它标识一个订阅者是否正在订阅中,订阅后置为true,解绑后置为false,如果用户连续调用解绑,redux判断isSubscribed为false,就直接return了。
  3. redux设置了currentListnersnextListners两个数组,这两个数组就是为了防止执行listners时候还添加和移除监听器。在添加和移除时候都新建一个区别于currentListners的数组:nextListeners,在nextListners添加或删除listener,当dispatch时候再将currentListnersnextListners同步。

redux的createStore就是实现了上面提到的API并且完美解决了上面提到的问题。

阅读redux代码,可以理解的更深刻:redux-githubredux createStore源码