像仓管一样管理redux-仓管也需要才艺(中间件)

202 阅读2分钟

仓管,仓管!!!我们需要一双翅膀

回忆哈!出货单是action, reducer是货物, dispatch是仓管。

问题来了,现在的仓管职责太单一了,收获,发货,通知。

现在我们要求仓管多才多艺,比如在收货前唱首激昂的歌曲(打印日志), 收完货吟唱首抒情的小诗。就好比我们公司,没得点才艺都进不来。不然年会谁去呀?^V^

小小的我们,小小的才艺

一句代码教你如何添加才艺:

// 假设store仓库
let dispatch = store.dispatch;
function logger(action) {
    console.log('我心中有一首歌');
    dispatch(action);
    console.log('我再吟一首诗');
}
// 再重新赋值,既保留了原来的,功能,又在之前的功能上增强了。
dispatch = logger

仓管才艺注册中心

接下来我们把注册中间件的方法叫做applyMiddleware。

// 第一步肯定是传入中间件
function applyMiddleware(middleware) {
    // 传入仓库创建方法
    return function(createStore) {
        // 创建仓库,我们需要reducer
        return function(reducer) {
            // 返回仓库
            let store = createStore(reducer);
            let dispatch;
            let middlewareApi = {
                getState: store.getState,
                dispatch: (action) => dispatch(action)
            }
            middleware = middleware(middlewareApi);
            dispatch = middleware(store.dispatch);
            return {
                ...store,
                dispatch
            }
        }
    }
}

然后我们写一个自己的中间件

function logger({getState, dispatch}) {
    // dispatch是新包装的dispatch
    return function(next) {
        // next是下一个中间件,没有就是原来的dispatch
        return function(action) {
            console.log('我心中有一首歌');
            next(action);
            console.log('我再吟一首诗');
        }
    }
}

从上面我们看出只处理了一个中间件,那么多个中间件,如何处理。那就是包装。举个小栗子。

function add1(str) {
    return str
}

function add2(str) {
    return str + ':'
}

function add3(str) {
    return str + 'hello'
}
// 现在我们希望,add1的结果add2的参数,add2的结果当add3的参数

add3(add2(add1('王先生')))

那么我们写个方法来聚合,就叫compose好了

function compose(...fns) {
    if(fns.length==1) return fns[0];
    return fns.reduce((preFn, curFn) => {
        return (...arg) => {
            return curFn(preFn(...arg))
        }
    })
}

优化仓库注册中心

把我们之前的代码组织哈,就是我们完整的中间件注册了。

function applyMiddleware(middlewares) {
    // 传入仓库创建方法
    return function(createStore) {
        // 创建仓库,我们需要reducer
        return function(reducer) {
            // 返回仓库
            let store = createStore(reducer);
            let dispatch;
            let middlewareApi = {
                getState: store.getState,
                dispatch: (action) => dispatch(action)
            }
            middlewares = middlewares.map(middleware => middleware(middlewareApi));
            dispatch = compose(...middlewares)(store.dispatch);
            return {
                ...store,
                dispatch
            }
        }
    }
}

流行时尚才艺-中间件

thunk中间件

function thunk({getState, dispatch}) {
    return function(next) {
        return function(action) {
            if(typeof action === 'function') {
                action(dispatch, getState);
            }else{
                next(action);
            }
        }
    }
}

promise中间件

function redux-promise({getState, dispatch}) {
    return function(next) {
        return function(action) {
            if(action.then && typeof action.then === 'function') {
                action.then(dispatch);
            }else if(action.payload&& action.payload.then&& typeof action.payload.then == 'function'){
                action.payload.then(payload => dispatch({...action, payload}), payload => dispatch({...action, payload}));
            }else{
                next(action);
            }
        }
    }
}

总结

实践出真理,中间件给我们更多方式去处理代码,像处理异步,打印日志等。