Redux源码分析--Middleware(1)

Redux源码分析:

Middleware可以意为中间件,Reudx middleware作用于dispatch,丰富了dispatch的功能,也可以认为是store enhancer(store增强器)。Redux Middleware主要工作在action发起之后,到达reducer之前。

Redux middleware主要解决:进行日志记录、异步请求、创建崩溃报告等

Redux middleware实现模式:

    ({getState, dispatch}) => (next) => (action) => {}

下面分析下applyMiddleware.js源码

export default function applyMiddleware(...middlewares) {
  return createStore => (...args) => {
    const store = createStore(...args)
    let dispatch = () => {
      throw new Error(
        'Dispatching while constructing your middleware is not allowed. ' +
          'Other middleware would not be applied to this dispatch.'
      )
    } 

    const middlewareAPI = {
      getState: store.getState,
      dispatch: (...args) => dispatch(...args)
    }
    const chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

上面是applyMiddleware.js所有源码,就聊聊十几行,为了更好分析源码,我们先分析下下面两个问题

一、解释下为啥middleware的实现模式为() => () => () => {}

  1. 从代码const chain = middlewares.map(middleware => middleware(middlewareAPI))中,我们知道,在这里,middleware将执行一次,并将{getState, dispatch}作为参数传入,因此我们写middleware模式时,是({getState, dispatch}) => ...
  2. 对于dispatch = compose(...chain)(store.dispatch),compose是将一系列函数组合成一个函数,如果你想了解compose,请跳转至compose介绍。store.dispatch将作为compose最右边参数函数的参数运行,返回一个函数() => {},赋值给dispatch。因此middleware模式变为({getState, dispatch}) => (next) => ....
  3. middleware实质是丰富了dispatch功能的enhancer,最后,我们还需要dispatch(action),来进行state的修改,所以说最后还要进行(action) => {}

因此middleware的实现模式为({getState, dispatch}) => (next) => (action) => {}

二、为什么({getState, dispatch}) => (next) => (action) => {}中是next,而不是dispatch,因为我们明明是传入的是store.dispatch

dispatch = compose(...chain)(store.dispatch)中,store.dispatch作为参数传入的只是compose参数中最右边函数,如果是applyMiddleware中传入的最有边的中间件,你可以写成dispatch,但是所有的中间件中,你写成dispatch就不合适了,其实next指向的(action) => {},下面用一个实例来说明:

let m1 = ({ dispatch, getState }) => (next) => (action) => {
	console.log('m1');
	console.log(next);
	return next(action);
}

let m2 = ({ dispatch, getState }) => (next) => (action) => {
	console.log('m2');
	console.log(next);
	return next(action);
}

let store = applyMiddleware(m1, m2)(createStore)(reducer)

m1, m2就是定义的两个中间件,控制台上输出结果:

三、在applyMiddleware.js源码中,为啥是dispatch: (...args) => dispatch(...args)而不是dispatch:dispatch

写成dispatch: (...args) => dispatch(...args)这种形式,可以认为是一个闭包,dispatch将会是一个动态的,毕竟我们会重新给dispatch赋值,dispatch = compose(...chain)(store.dispatch),其实你阅读很多插件源码,都会发现,闭包的使用是一个十分广泛的。下面用一个实例来解释这个问题:

let p = () => {
	let d = () => {console.log('start')};
	let o = {
		d: (args) => d(args)
	}
	setTimeout(() => {
		d = () => {console.log('1秒后...')}
	}, 1000);

	setTimeout(() => {
		//2秒后执行
		o.d();
	}, 2000);
}

p();

结果返回:1秒后...

如果将d: (args) => d(args)改为d: d,则返回结果变为start

四、dispatch最初定义的抛出异常函数什么时候调用

'Dispatching while constructing your middleware is not allowed. Other middleware would not be applied to this dispatch.'。这是初始dispatch函数的时候,抛出的异常内容。其实使用dispatch还没有进行dispatch  = compose(...chain)(store.dispatch)的时候,具体就是在(action) => {}之前,即({getState, dispatch)} => (next) => 的时候。具体说明:

比如:当在({getState, dispatch}) => {}中调用dispatch(action)时

let m1 = ({getState, dispatch}) => {
	console.log('m1====', dispatch);
	dispatch({type: 'THROW_ERROR'});

	return (next) => (action) => {next(action)}
}

let store = applyMiddleware(m1)(createStore)(reducer)

结果:

当({getState, dispatch}) => (next) => {}中调用dispatch(action),一直报相式问题

这个throw Error保证了dispatch = compose(..chain)(store.dispatch)运行结束,即在(action) => {}这一步

这一章主要解决在学习applyMiddleware.js源码时,产生的一系列问题,下一章,将介绍Middleware在运行时的整个详细的过程,及中间件内部代码什么时候运行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值