头图

compose method

compose function definition

The compose method uses the reduce method of the array to combine multiple methods into one method in a certain order, so as to achieve the effect automatically and orderly executing The order of execution of each method depends on how the reduce method is applied. The simple implementation of compose is as follows:

// compose 接受多个函数作为入参 fun1 fun2
function compose(...funs){
  const len = funs.length 
  // 处理两种特殊情况,函数数量 为 0 || 1
  if(!len) return (...arg) => arg
  if(len === 1) return funs[0]
  // 以下组合方式 b 方法 会 先于 a 方法执行
  return funs.reduce((a,b) => (...arg) => a(b(arg)))
  // 以下组合方式 a 方法会先于 b 方法执行
  // return funs.reduce((a,b) => (...arg) => b(a(arg)))
}

The form of the combined function (a, b)

  1. The return value of the b function is ordinary data, which is used as the input parameter of the a function

    function b(){
      // 如返回值为普通的对象
      return {...}
    }
    function a(arg){
      // arg 数据应用 || 处理
      return {...}
    }

    In this form of the above form, a is a function of the application b To function return value, best previously known function return value b data type field and details, which can lead to among a, b method coupled serious .

  2. b returns a function as the input parameter of a function

    function b(){
      // 返回值为函数
      return (...arg) => { 
     //...
      }
    }
    function a(next){
      // next 前置操作
      // next() 可以在这里操作 next
      // next 后置操作
      return (...arg) => {
     // next 前置操作
     // next() 可以在这里操作 next
     // next 后置操作
      }
    }

    Compared to the previous form, this form can be made between the function reaches decouple effect, that is a function of a do not care about the return value of the function b, just know it is the return value of a function, and they think the right time to call That is, this also controls the function call sequence at the same time, so as to achieve the execution effect similar to the onion model

    applyMiddleware method

    applyMiddleware function form

    Constructs the closure , which is an externally defined method and provides internally specified apis; the following example

    // 接受外部定义的方法数组 funs
    function applyMiddleware(...funs){
      const apis = {
     dispatch: () => ({})
      }
      // 遍历执行 外部定义的方法,构造一个闭包;并将返回值作为 结果返回
      return funs.map(fun => fun(apis))
    }

    Funs function form to be operated

    In order to construct a closure, fun's return value should be a function that uses apis.

    function myMiddleware1(apis){
      // 返回一个 方法,该方法中会调用 apis 中暴露的方法,形成一个闭包,
      return actions => {
      // apis 方法调用
      const { dispatch } = apis
     dispatch(actions)
      }
    }
    const myMiddlewareWrappers = applyMiddleware(myMiddleware1)
    // myMiddlewareWrappers 为 [actions => { const { dispatch } = apis; dispatch(actions);}] 

    There may be questions: Since it is just a function call in apis, why is it so complicated and realized with the help of closures? Can the caller achieve the goal directly by calling the functions inside the apis?

  3. Application of closures:

    1. Closures allows us external function control internal functions execution logic, as is common stabilization, closure function
    2. Using closures can achieve function currying, so as to achieve function into the parameter cache , and then achieve the effect of a singleton
  4. Why not directly call the internal method of apis:

    1. The internal method of apis does not exist at the beginning. It may be dynamically generated. The singleton effect mentioned in
    2. Usually we are not simply function calls, often with additional operations, not applying closures will lead to the following effects
    function fun1(arg){
      console.log(arg)
      apis.dispatch(arg)
    }
    function fun2(arg){
      arg.b = 100
      apis.dispatch(arg)
    }
    // apis 方法的调用可能会随处可见,但是仔细观察,apis 方法的调用其实都是重复的代码
    对比应用闭包的效果
    // 没有重复的 apis 内部函数调用,构造的闭包函数会自动执行 apis 内部的方法
    // apis 暴露了但是没有完全暴露
    const results = applyMiddleware(myMiddleware1,myMiddleware1)
    results[0](100)
    results[1](200)

    Combine

    How to combine compose and applyMiddleware to get the magic effect?
    First, consider the method in the form of myMiddleware defined above, and directly compose the method list obtained by applyMiddleware

    const myMiddlewareWrappers = applyMiddleware(myMiddleware1, myMiddleware2)
    // 通过 compose 将 方法列表组合为一个方法
    const result = compose(...myMiddlewareWrappers)
    // 此时 result 为何种形式呢?
    // 根据 compose 的 作用,不难想象 result 为一个函数
    // actions => myMiddleware1(myMiddleware2(actions))

    So far, compose has been combined with applyMiddleware.
    However, if you carefully observe the form of the myMiddleware1 and 2 functions, you will find some problems. The return value of the myMiddleware1 and 2 methods is not a function. After the analysis of compose at the beginning, it can be found that this form will bring about the problem of serious coupling Therefore, a one-step transformation of myMiddleware is required, as follows

    function myMiddleware3(apis){
      // 返回一个 方法,该方法中会调用 apis 中暴露的方法,形成一个闭包,
      // 同时为了 保证 compose 过程中 每个 函数的 入参仍然为 一个函数,需要将以下返回值再
      // 进行一层封装
      return next => actions => {
     // ...
     next(actions)
     // ...
      }
    }

    magic

    However, we still do not meet the above results. The call of apis internal functions is not in the hands of the function caller, that is, the function caller can only pass in one actions parameter, and cannot control the specific execution timing of the apis function. How to achieve the effect control inversion
    Actions can actually be a method. At this time, apis can be passed to actions by passing parameters, so that the control of apis is passed to the real function caller. as follows

    function myMiddleware2(apis){
     // 返回一个 方法,该方法中会调用 apis 中暴露的方法,形成一个闭包,
     return next => actions => {
       // 控制反转
       actions(apis)
     }
      }
    
      // 可以 结合myMiddleware2 与myMiddleware1 两种形式的函数实现兼容
      // 即 调用者需要 控制 apis 时通过 传入函数形式的 actions 即可,否则传入 apis 中指定形式入参即可
      function myMiddleware2(apis){
     // 返回一个 方法,该方法中会调用 apis 中暴露的方法,形成一个闭包,
     return next => actions => {
       // 控制反转
       if(typeof actions === 'function') return actions(apis);
       next(actions)
     }
    }

彭博
131 声望4 粉丝

前端小白