I don't quite understand the source code of compose function in redux.

the following is the source code of the compose method in Redux:

export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  const last = funcs[funcs.length - 1]
  const rest = funcs.slice(0, -1)
  return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
}

I hope to get your detailed analysis. Thank you

Mar.21,2021

I happen to have seen the redux source code, and easily answered, redux should be combined with redux-thunk and applyMiddleWare to see.

// redux-thunk.js
({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }

    return next(action);
  };
}
// applyMiddleWare.js
const chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)
export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

this product needs to be combined with redux-thunk to see
redux-thunk returns const a = next = > action = > {return next (action)}
assuming that there are other middleware, and the function of other middleware is also const b = next = > action = > next (action)
you calculate the effect of b (a) is the effect of compose.

the next of the first middleware is store.dispatch, and the next of the second is the result returned by the first function as the dispatch in the middle of the next, is the action = > next (action) after the execution of the middle.

The

compose function is a little abstract. You can try to write a middleware yourself to understand

.
export default ({ log = false, namespace }) => {
    if (typeof namespace !== 'string') throw new Error('options.namespace must be given.');
    return ({ dispatch, getState }) => next => action => {
        // state 
        const _r = next(action); // dispatch reducer  subscription
        // state
        const state = getState();
        if (log) console.log(state);
        sessionStorage.setItem(namespace, JSON.stringify(state));
        return _r; //  action
    }
}

I haven't seen the redux source code, but I can understand this compose function. Now let's talk about it:

first of all, compose passes in an indefinite number of function as parameters, and the number of parameters is greater than or equal to 2. In fact, what executes the process is to call a string of function queues, calling from right to left, and explain by executing the compose method:

compose(fn1 ,fn2, fn3, ...fn[n-2],fn[n-1],fnn)(...args) ;   

the above execution process is equivalent to:

 
 fn1(fn2(......(fn[n-2](fn[n-1](fnn(...args))))))

and then the clear point is:

 compose(a,b,c,d)(...args) = a(b(c(d(...args))))

take a look at the native methods of Array, reduce and reduceRight, and you will soon understand.

< hr >

Today, I went to look at the redux source code and found that the writing method had changed, and the last step became

.
 return funcs.reduce((a, b) => (...args) => a(b(...args)))

in fact, the execution process is the same as above, but written differently


learn about Array's reduce function to understand

Menu