Redux中的middleware

middleware

What:

定义:middleware(中间件),用来简化和隔离这些基础设施和业务逻辑之间的细节,让开发着能够关注在业务的开发上,以提高开发效率.


  1. 在express和koa等服务端框架中,middleware是指可以被嵌入在框架接收请求到产生响应过程中的代码.(比如:可以在express的middleware中完成添加CORS headers,记录日志,内容压缩等工作.)
  2. Reaux中,middleware提供的是位于action被发起后,到达reducer之前的扩展点.可以用其进行日志记录,创建崩溃报告,调用异步接口或者路由等等.
    盗张图
    这是一个简单的数据流图,点击button分发一个action,进入reducer,reducer接收到action更新state并重新渲染view.


    那么,如果我们需要点击button从服务端获取数据,只有在等待获取完成之后,才可进行页面的render,这样会阻塞页面的展示.由此,我们利用middleware来增强dispatch.
    再盗张图:

使用middleware处理事件的逻辑.

How:

Redux提供了applyMiddleware来装载middleware:

//应用了函数的柯理化(currying),使用一种单参函数来使用参数的方法.
//applyMiddleware
import compose from './compose';

//通过不断currying形成的middleware积累参数,配合compose,形成pipeline处理数据流.
//共享store,因为闭包的存在,在applyMiddleware完成后,middleware内部拿到的store是最新的 

export default function applyMiddleware(...middlewares) {
    return (next)=>(reducer,initialState)=>{
        let store=next(reducer,initialState);
        let dispatch=store.dispatch;
        let chain=[];
        //给middleware分发store
        let middleWareAPI={
            getState:store.getState,
            dispatch:(action)=>dispatch(action)
        };

 //让每个middleware带着middlewareAPI这个参数执行一遍,然后获得带着相同的store.
   chain=middlewares.map(middleware=>middleware(middleWareAPI));

   //所有chain中的函数组装成一个新的函数,新的dispatch,然后进行执行.
   //newDispatch=fn1(fn2(fn3(store.dispatch)))

        dispatch=compose(...chain)(store.dispatch);
        return {
            ...store,
            dispatch
        };
    };
}

//logger
export default store => next => action => {
    console.log('dispatch:', action);
    next(action);
    console.log('finish:', action);
}

粘贴的compose代码:

export default function compose(...funs) {
    if (funs.length === 0) {
        return arg = arg;
    }
    if (funs.length === 1) {
        return funcs[0];
    }
    //获取最后一个函数
    const last=funs[funs.length - 1];
    //获取除最后一个以外的函数中[0,length-1]
    const rest = funs.slice(0, -1);
    //通过函数curry化
    return (...args) => rest.reduceRight((compose, f) => f(composed), last(...args))
}

最后:现在每个middleware都可以访问store,每个middlewareAPI这个变量,拿到diapatch这个属性之后,middleware中调用store.dispatch(),传入action,这样middleware通过next(action)层层处理.往往用于异步请求的需求里.

注:
确保在middleware中调用的是store.dispatch(action)而不是next(action),那么这个操作会再次遍历包含当前middleware在内的整个middleware链.(异步非常有用).
为了保证只能应用一次middleware一次,他作用于createStore()上而不是store本身,因此它的签名不是(store,middlewares)=>store,而是(…middlewares)=>crateStore=>createStore.createStore() 也接受将希望被应用的函数作为最后一个可选参数传入。

最终方法:官网上有七个呐

这里记两个自己感觉好玩的

/**
 * 除了 action 之外还可以发起 promise。
 * 如果这个 promise 被 resolved,他的结果将被作为 action 发起。
 * 这个 promise 会被 `dispatch` 返回,因此调用者可以处理 rejection。
 */

const vanillaPromise=store=>next=>action=>{
    if(typeof action.then!=='function'){
        return next(action);
    }
    return Promise.resolve(action).then(store.dispatch)
};
/**
 * 用 { meta: { delay: N } } 来让 action 延迟 N 毫秒。
 * 让 `dispatch` 返回一个取消 timeout 的函数。
 */
const timeoutScheduler = store => next => action => {
    if (!action.meta || !action.meta.delay) {
        return next(action);
    }

    let timeoutId=setTimeout(
        ()=>next(action),
        action.meta.delay
    );

    return function cancel() {
        clearTimeout(timeoutId)
    }
};

参考文章1
参考文章2

猜你喜欢

转载自blog.csdn.net/qq_39083004/article/details/80300854
今日推荐