4redux源码解析 - 糅合多种dispatch

Posted liujc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4redux源码解析 - 糅合多种dispatch相关的知识,希望对你有一定的参考价值。

在开发时,也许需要更多地包装dispatch以实现更加完善的功能。
比如包装 dispatch来打印日志,包装dispatch以支持Promise,各种包装需要密切配合。

之前两篇代码的汇总:

//包装dispatch来打印日志
const addLoggingToDispatch = (store) => {
  const rawDispatch = store.dispatch;
  if(!console.group){
    return rawDispatch;
  }
  return (action) => {
    console.group(action.type);
    console.log(‘%c previous state‘, ‘color: gray‘, store.getState());
    console.log(‘%c action‘, ‘color: blue‘, action);
    const returnValue = rawDispatch(action);
    console.log(‘%c previous state‘, ‘color: gray‘, store.getState());
    console.log.group(action.type);
    return returnValue
  }
}
//dispatch支持传入promise对象
const addPromiseSupportToDispatch = (store) => {
  const rawDispatch = store.dispatch;
  return (action) => {
    if(typeof action.then === ‘function‘){
      return action.then(rawDispatch);
    }
    return rawDispatch(action);
  }
}

为了使这两种方式同时运作,可以写一个用来初始化sotre的函数,以丰富store.dispatch的功能。

const configureStore = () => {
  const store = createStore(App);
  if(process.env.NODE_ENV !== ‘production‘){
    store.dispatch = addLoggingToDispatch(store);
  }
  store.dispatch = addPromiseSupportToDispatch(store);
  return store;
}

这样便返回了一个包含有增强型dispatch的store,
仔细研究configureStore函数,我们发现addPromiseSupportToDispatch方法返回了一个符合正常用法的dispatch,
此时它支持dispatch参数是一个promise,它会等待Promise resolve后,利用rawDispatch再次进行action派发。
那么这个rawDispatch是最初、最原始的dispatch吗?在开发环境下,显然不是。因为执行sotre.dispatch = addPromiseSupportToDispatch(store)之前,
已经执行了store.dispatch = addLoggingToDispatch(store)。
换名话说,在执行addPromiseSupportToDispatch时,store.dispatch是上一个包装版本的sotre.dispatch。
明白了这层关系,我们就会想到rawDispatch这个全名不十分准确,它本意是最原始的store.dispatch , 但是在代码执行
时,每一个中间件所获得的store.dispatch都已经被改造,我们将其命名为next。
前面的例子改造之后:

const addLoggingToDispatch = (store) => {
  const next = store.dispatch;
  if(!console.group){
    return next
  }
  return (action) => {
    //...
    const resultValue = next(action);
    //...
    return resultValue;
  }
}
const addPromiseSupportToDispatch = (store) => {
  const next = store.dispatch;
  return (action) => {
    if(typeof action.then === ‘function‘){
      return action.then(next)
    }
    return next(action);
  }
}

为了避免上面这样零散地修改公共的api接口,我们可以将这种包装过程收敛 - 声明一个数组,即中间件数组。
它的每一项都是一个中间件,然后统一根据中间件来增强dispatch。

const configureStore = () => {
  const store = createStore(App);
  const middleWare = [];

  if(process.env.NODE_ENV !== ‘production‘){
    middleWare.push(addLoggingToDispatch);
  }
  middleWare.push(addPromiseSupportToDispatch);
  wrapDispatchWithMiddlewares(store, middlewares);
  return store;
  
}
 以上代码中,并不直接执行addLoggingToDispatch和addPromiseToDispatch,而
 是将其push到middlewares数组,然后统一执行。这里说的统一执行就是指代码中的wrapDispatchWithMiddleWares(store, middlewares);


 const wrapDispatchWithMiddlewares = (store, middlewares) => {
  middlewares.forEach(middleware => {
    store.dispatch = middleware(store)(store.dispatch);
  })
 }

 

以上是关于4redux源码解析 - 糅合多种dispatch的主要内容,如果未能解决你的问题,请参考以下文章

Flink1.15源码解析--启动JobManager----Dispatcher启动

Flink1.15源码解析--启动JobManager----Dispatcher启动

Picasso源码解析

APIView之dispatch中认证与权限源码刨析:

drf 解析模块 异常模块 响应模块 序列化组件

DRF ---- APIview生命周期 请求/渲染/解析/异常/响应/ 模块源码 drf配置