【Redux】自己动手实现redux-thunk

1. 前言

        在原始的redux里面,action必须是plain object,且必须是同步。而我们经常使用到定时器,网络请求等异步操作,而redux-thunk就是为了解决异步动作的问题而出现的。

2. redux-thunk中间件实现源码
function createThunkMiddleware(extra) {
    return ({ dispatch, getState}) => next => action => {
        if(typeof action === 'function') {
            return action(dispatch, getState, extra);
        }
        return next(action);        
    }
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
2.1 此处dispatch = compose(...chain)(store.dispatch)
  • action(dispatch)中的这个dispatch可能并不是store.dispatch
  • action(dispatch)执行后,如果action函数体使用dispatch({...}),动作{...}也会层层传递下去,直到传递给store.dispatch({...})
  • 举个例子,比如说dispatch= f(g(h(store.dispatch)))),那么action(dispatch)函数体中执行到dispatch({...}),动作传递过程是: f(g(h(store.dispatch)))({...}) -> g(h(store.dispatch))({...}) -> h(store.dispatch)({...}) -> store.dispatch({...})
2.2 此处next的对应关系

        继续举个例子,比如说dispatch = f(g(h(store.dispatch))))

  • 如果当前中间件指向f,则next对应g(h(store.dispatch))
  • 如果当前中间件指向g,则next对应h(store.dispatch)
  • 如果当前中间件指向h,则next对应store.dispatch(真实的dispatch)
3. redux中applyMiddleware方法源码
export const applyMiddleware = (...middlewares) => {
    return createStore => (reducer, preloadedState) => {
        const store = createStore(reducer, preloadedState);
        let dispatch = () => {
            throw new Error('xxxx');
        };
        const middlewareAPI = {
            getState: store.getState,
            dispatch: (action, ...args) => dispatch(action, ...args)
        };
        const chain = middlewares.map(middleware => middleware(middlewareAPI));
        dispatch = compose(...chain)(store.dispatch);
        return {
            ...store,
            dispatch
        }
    }
};

export const compose = (...funcs) => {
    if(funcs.length === 0) {
        return arg => arg;
    }
    if(funcs.length === 1) {
        return funcs[0];
    }
    return funcs.reduce((prev, cur) => {
        return (...args) => {
            prev(cur(...args));
         } 
     });
}
4. redux中createStore增加第3个参数
export const createStore = (reducer, preloadedState, enhancer) => {
    // 初始化state
    let state = preloadedState;
    // 保存监听函数
    const listeners = [];
    // 返回store当前保存的state
    const getState = () => state;
    // 通过subscribe传入监听函数
    const subscribe = (listener) => {
        listeners.push(listener);
    }
    // 执行dispatch,通过reducer计算新的状态state
    // 并执行所有监听函数
    const dispatch = (action) => {
        state = reducer(state, action);
        for(const listener of listeners) {
            listener();
        }
    }
    !state && dispatch({});
    if(enhancer) {
        return enhancer(createStore)(reducer, preloadedState);
    }
    return {
        getState,
        dispatch,
        subscribe,
    }
}

注:以上,如有不合理之处,还请帮忙指出,大家一起交流学习~  

你可能感兴趣的:(前端开发,前端,javascript,开发语言)