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地址:本文实例完整源码地址