聊聊redux里compose函数|8月更文挑战

487 阅读2分钟

compose

  • compose的函数作用就是组合函数的,将函数串联起来执行。将多个函数组合起来,一个函数的输出作为是另一个函数的输入参数,一旦第一个函数开始执行,就会像多米诺骨牌一样推导执行。
  • 上一个函数的返回值作为下一个函数的参数进行执行

实现原理

例如,实现以下函数顺序执行,且上一个函数的返回值作为下一个函数的参数

  function f1(arg) {
    console.log('f1', arg);
    return 'f1' + arg;
  }

  function f2(arg) {
    console.log('f2', arg);
    return 'f2' + arg;
  }

  function f3(arg) {
    console.log('f3', arg);
    return 'f3' + arg;
  }

实现1 直接调用

直接调用f1(),使得f1()的返回值作为f2的参数,同理。f3的参数是f2的返回值

f3(f2(f1('omg')));

实现2 for循环

把多个函数放入一个数组里,进行遍历

    let fns = [f1, f2, f3];
    let curFlag = '12';
    for (let i = 0; i < fns.length; i++) {
      curFlag = fns[i](curFlag);
    }

实现3 聚合函数compose

利用数组的reduce 函数,实现compose 函数,此时不管你有多少个函数被依次调用,都可以用聚合函数

  function compose(...fns) {
    return (arg) => {
      return fns.reduce((preFn, curFn) => {
        console.log('preFn', preFn);
        return curFn(preFn);
      }, arg);
    };
  }
 function compose(...fns) {
    return fns.reduce((preFn, curFn) => (arg) => curFn(preFn(arg)));
  }

实现一个redux里applyMiddleware函数,多个中间件

  • applyMiddleware 里接收多个中间件,redux 是一个纯粹的状态管理器,默认只支持同步,如若需要实现异步任务,比如延迟,网络请求。

  • 需要中间件的支持。

  • applyMiddleware的主要功能是改写createStore中的dispatch方法,并且可以将多个middleware组合到一起,形式链式的调用,前后互不影响

  • applyMiddleware函数其实就是将一个加强版的dispatch返回给我们。

  • 在createStore 时调用 applyMiddleware,

  • 此时我们调用的dispatch 则是已经通过applyMiddleware处理过的dispath。它可以帮我们处理多种情况的任务

function compose(...fns) {
  return fns.reduce((preFn, curFn) => (arg) => curFn(preFn(arg)));
}

export default function (...middlewares) {
  return (createStore) => (reducer) => {
    let store = createStore(reducer);
    let dispatch = store.dispatch;

    // 对仓库的控制权,set and get
    const midApi = {
      getState: store.getState,
      dispatch: (action) => dispatch(action), // 新的dispath
    };

    // 把仓库的控制权放到我的中间件中去处理
    const chain = middlewares.map((middleware) => middleware(midApi));

    // 加强dispatch -> 先执行中间件。再执行dispatch
    dispatch = compose(...chain)(store.dispatch);
    
    return {...store, dispatch};
  };
}