手动编写redux中间件,compose合并中间件过程和原理解析(函数柯里化思想)

github地址:本文实例完整源码地址

中件件的原理是dispatch(action)之前进行其他操作:代码实例:

单个中间件:

const next = store.dispatch;
const dispatchImitation = function(action){
	console.log('我是中间件')
	next(action)
}
//原来的disptch(action)变为:
dispatchImitation(action)

多个中间件:(这个是实现中间件的基本原理

//多个中间件串行 得出如下写法
//每个中间件返回一个接收action为参数的函数,当作下一个中间件的next方法,最初的next是store.dispatch
const dispatchImitation1 = next => action => {
	console.log('中间件1')
	return next(action)
}
const dispatchImitation2 = next => action => {
	console.log('中间件2')
	return next(action)
}

dispatchImitation = dispatchImitation1(dispatchImitation2(dispatch))

//逻辑分析
//dispatchImitation1(dispatch)  会返回:

// function(action){
// 	return dispatch(action)
// }

// dispatchImitation2(
// 	function(action){
// 		return dispatch(action)
// 	}
// )

// //执行过后为:
// action => {
// 	return  (
// 			    function(action){
// 					return dispatch(action)
// 				}
// 			)(action)
// }

上面代码的主要原理是:在一个中间件中先不执行dispatch(),而是返回一个函数返回值为dispatch(action)的函数,再用这个函数去执行其他的中间件

再深入:

redux提供了applyMiddleware方法来增加中间件,根据其源码可以得到中间件的api

applyMiddleware(这里在源码基础上加了注释)

middleware({
          getState: store.getState,
          dispatch: (action) => dispatch(action)
})

可以看到每个中间件首先接收一个对象为参数

{
          getState: store.getState,
          dispatch: (action) => dispatch(action)
}

function myApplyMiddleware(...middlewares){
	return (createStore) => (reducer, preloadedState, enhancer) => {
		var store = createStore(reducer, preloadedState, enhancer);
		var dispatch = store.dispatch;
		var chain = [];
	 
		var middlewareAPI = {
		  getState: store.getState,
		  dispatch: (action) => dispatch(action)
		};
		chain = middlewares.map(middleware => middleware(middlewareAPI));
		dispatch = compose(...chain)(store.dispatch);
		return {...store, dispatch}
	  }
}

所以就有了中间件的基本编写api:

const middleWare = function(){
    return ({dispatch, getState}) => next => action => {
        console.log('中间件2')
        return next(action)
    }
}

看实例:

编写三个中间件


//中间件1
const middleWare1 = function(){
    return ({dispatch, getState}) => next => action => {
		console.log('中间件1')
		//这里是异步中间件
		return setTimeout(() => {
			next(action)
		},1000)
        //return next(action)
    }
}

const middleWare2 = function(){
    return ({dispatch, getState}) => next => action => {
        console.log('中间件2')
        return next(action)
    }
}

const middleWare3 = function(){
    return ({dispatch, getState}) => next => action => {
        console.log('中间件3')
        return next(action)
    }
}

添加并执行

let store = createStore(
	reducer,
	myApplyMiddleware(
	   middleWare1(),middleWare2(),middleWare3()
	)
)

运行过程分析和详解:

对于applyMiddleware:


function myApplyMiddleware(...middlewares){
	return (createStore) => (reducer, preloadedState, enhancer) => {
		var store = createStore(reducer, preloadedState, enhancer);
		var dispatch = store.dispatch;
		var chain = [];
	 
		var middlewareAPI = {
		  getState: store.getState,
		  dispatch: (action) => dispatch(action)
		};
		chain = middlewares.map(middleware => middleware(middlewareAPI));
		/**中间件数组  接收next 返回接收action为参数的函数
		 *  [
				function(next) {
					return function (action) {
							console.log('中间件1'); //这里是异步中间件
							return setTimeout(function () {
							next(action);
						}, 10000);
					}
				},
				function(next) {
					return function (action) {
						console.log('中间件2'); //这里是异步中间件
				
						return next(action);
					}
				},
				function(next) {
					return function (action) {
						console.log('中间件3'); //这里是异步中间件
				
						return next(action);
					}
				}
			]
		 */
		//console.log(...chain)
		//console.log('合并之后的函数:',compose(...chain).toString())
		dispatch = compose(...chain)(store.dispatch);
	    //console.log(dispatch,'改造后的dispatch')
		return {...store, dispatch}
	  }
}

对于dispatch = compose(...chain)(store.dispatch)

看下compose函数:这里在源码基础上进行了函数细化

关于reduce函数参见我的另外一篇文章:redux原理——ruduce函数和compose函数

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)))
	return funcs.reduce(function(a,b,currentIndex){
		//console.log(a.toString(),currentIndex)
		return function(...args){
			//console.log('这里传入了参数',args.toString())
			return a(b(...args))
		}
	})

	/**
	 * 解析该函数 假设执行三次 ,参见middleware-analysis.js文件
	 */
}

这里有了一个reduce函数,reduce函数的作用就是函数合并,这里是实现最初的链式调用

执行原理详解:

这样就实现了在运行时的链式调用,这里时从左向右执行中间件。

github地址:本文实例完整源码地址

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值