Redux中的middleware

刺骨的言语ヽ痛彻心扉 2022-05-25 10:58 260阅读 0赞

middleware

What:

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


  1. 在express和koa等服务端框架中,middleware是指可以被嵌入在框架接收请求到产生响应过程中的代码.(比如:可以在express的middleware中完成添加CORS headers,记录日志,内容压缩等工作.)
  2. Reaux中,middleware提供的是位于action被发起后,到达reducer之前的扩展点.可以用其进行日志记录,创建崩溃报告,调用异步接口或者路由等等.
    盗张图
    这是一个简单的数据流图,点击button分发一个action,进入reducer,reducer接收到action更新state并重新渲染view.
  1. 那么,如果我们需要点击button从服务端获取数据,只有在等待获取完成之后,才可进行页面的render,这样会阻塞页面的展示.由此,**我们利用middleware来增强dispatch**.
  2. ![再盗张图:][70 1]

使用middleware处理事件的逻辑.

How:

Redux提供了applyMiddleware来装载middleware:

  1. //应用了函数的柯理化(currying),使用一种单参函数来使用参数的方法.
  2. //applyMiddleware
  3. import compose from './compose';
  4. //通过不断currying形成的middleware积累参数,配合compose,形成pipeline处理数据流.
  5. //共享store,因为闭包的存在,在applyMiddleware完成后,middleware内部拿到的store是最新的
  6. export default function applyMiddleware(...middlewares) {
  7. return (next)=>(reducer,initialState)=>{
  8. let store=next(reducer,initialState);
  9. let dispatch=store.dispatch;
  10. let chain=[];
  11. //给middleware分发store
  12. let middleWareAPI={
  13. getState:store.getState,
  14. dispatch:(action)=>dispatch(action)
  15. };
  16. //让每个middleware带着middlewareAPI这个参数执行一遍,然后获得带着相同的store.
  17. chain=middlewares.map(middleware=>middleware(middleWareAPI));
  18. //所有chain中的函数组装成一个新的函数,新的dispatch,然后进行执行.
  19. //newDispatch=fn1(fn2(fn3(store.dispatch)))
  20. dispatch=compose(...chain)(store.dispatch);
  21. return {
  22. ...store,
  23. dispatch
  24. };
  25. };
  26. }
  27. //logger
  28. export default store => next => action => {
  29. console.log('dispatch:', action);
  30. next(action);
  31. console.log('finish:', action);
  32. }

粘贴的compose代码:

  1. export default function compose(...funs) {
  2. if (funs.length === 0) {
  3. return arg = arg;
  4. }
  5. if (funs.length === 1) {
  6. return funcs[0];
  7. }
  8. //获取最后一个函数
  9. const lastfuns[funs.length - 1];
  10. //获取除最后一个以外的函数中[0,length-1]
  11. const rest = funs.slice(0, -1);
  12. //通过函数curry化
  13. return (...args) => rest.reduceRight((compose, f) => f(composed), last(...args))
  14. }

最后:现在每个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() 也接受将希望被应用的函数作为最后一个可选参数传入。

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

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

  1. /** * 除了 action 之外还可以发起 promise。 * 如果这个 promise 被 resolved,他的结果将被作为 action 发起。 * 这个 promise 会被 `dispatch` 返回,因此调用者可以处理 rejection。 */
  2. const vanillaPromise=store=>next=>action=>{
  3. if(typeof action.then!=='function'){
  4. return next(action);
  5. }
  6. return Promise.resolve(action).then(store.dispatch)
  7. };
  8. /** * 用 { meta: { delay: N } } 来让 action 延迟 N 毫秒。 * 让 `dispatch` 返回一个取消 timeout 的函数。 */
  9. const timeoutScheduler = store => next => action => {
  10. if (!action.meta || !action.meta.delay) {
  11. return next(action);
  12. }
  13. let timeoutId=setTimeout(
  14. ()=>next(action),
  15. action.meta.delay
  16. );
  17. return function cancel() {
  18. clearTimeout(timeoutId)
  19. }
  20. };

参考文章1
参考文章2

发表评论

表情:
评论列表 (有 0 条评论,260人围观)

还没有评论,来说两句吧...

相关阅读