Redux源码分析--Enhancer
作者:互联网
store enhancer翻译成中文是store增强器,store middleware实质也是一种enhancer的实现,store middleware增强的dispatch的功能。store enhancer的实现不仅仅是丰富dispatch作用,你也可以通过createStore(reducer, preloadedState, enhancer)创建的store对象新增新的方法等等
在Redux源码中,涉及到enhancer的代码非常少,就仅仅几行。前面的判断都是对createStore传参进行判断:1、如果第二个参数preloadedState为函数,第三个没有传,那将enhancer = preloadedState, preloadedState = undefined 2、enhancer不能有多个,有且一个。如果都满足的话,enhancer又存在,执行enhancer(createStore)(reducer, preloadedState),enhancer函数的内部内容,自己去实现
通过enhancer(createStore)(reducer, preloadedState)来确定enhancer的实现模型是:
(createStore) => (reducer, preloaderState) => {}
如果想进行多个enhancer,怎么样呢,这就需要用到我们之前介绍的compose了,compose功能是将多个函数,合并成一个函数,就满足了createStore的要求了。如果你想了解compose,请跳转至Redux源码分析--compose
if (
(typeof preloadedState === 'function' && typeof enhancer === 'function') ||
(typeof enhancer === 'function' && typeof arguments[3] === 'function')
) {
throw new Error(
'It looks like you are passing several store enhancers to ' +
'createStore(). This is not supported. Instead, compose them ' +
'together to a single function.'
)
}
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState
preloadedState = undefined
}
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
return enhancer(createStore)(reducer, preloadedState)
}
下面我们举例来说明:
比如你想要用enhancer来实现一个state改变前改变后日志:
let enhanncer = (createStore) => (reducer, preloadedState) => {
let store = createStore(reducer, preloadedState);
let dispatch = (action) => {
//dispatch(action)之前state的值
console.log('before: ', store.getState());
store.dispatch(action);
//dispatch(action)之后state的值
console.log('after: ', store.getState());
return action;
}
return {
...store,
dispatch
}
}
let store = createStore(reducer, enhancer);
如果有多个enhancer,怎么实现呢?
使用compose将其组合成一个函数,如下实例:
let e1 = (createStore) => (reducer, preloadedState) => {
console.log('e1: ', createStore);
let store = createStore(reducer, preloadedState);
console.log('e1-after');
return {
...store
}
}
let e2 = (createStore) => (reducer, preloadedState) => {
console.log('e2: ', createStore);
let store = createStore(reducer, preloadedState);
console.log('e2-after');
return {
...store
}
}
let e3 = (createStore) => (reducer, preloadedState) => {
console.log('e3: ', createStore);
let store = createStore(reducer, preloadedState);
console.log('e3-after');
return {
...store
}
}
let enhancer = compose(e1, e2, e3);
let store = createStore(reducer, enhancer);
运行结果:
从上述结果可以分析可以看出:当进行多个enhancer(增强器)时,使用compose合并成一个enhancer,一系列的enhancer运行前后,compose从左到右依次运行,当执行某个enhancer时,如果执行到(createStore) => {}中的createStore(reducer,preloadedState)时,执行转到下一个enhancer,因为当前的createStore不是真正的createStore(),而是下一个enhancer的(reducer,preloadedState) => {}。当执行到最右边的enhancer,在反向往最左边依次执行,就如结果显示的一样,
e1 e2 e3 e3-after e2-after e1-after
enhancer和middleware怎么转换呢?
本质上middleware其实就是一个enhancer,只不过middleware只是在丰富dispatch,那么我们怎么把middleware转换成enhancer来使用呢?
compose(enhancer1, enhancer2, applyMiddleware(middleware1, middleware2))
当异步和同步middleware同时进行时,位置该如何存放呢?
异步功能的middleware存放在applyMiddleware的最右边,因为如果放在其他位置,可能对于其右边的middleware会不起作用。
当middleware和enhancer都存在的时候,代码的执行顺序是怎么样呢?
你可以这样理解:因为enhancer是增强store功能,肯定是在dispatch(action)之前运行,即代码初始阶段,而Middleware是需要action,才能执行(action) => {},所以middleware中的(action) => {}代码才晚于enhancer。
源码分析如下:
1、根据let store = applyMiddleware(m1, m2, m3)(createStore)(reducer, preloadedState, compose(e1, e2, e3)),那么代码应该先执行applyMiddleware()方法,由于applyMiddleware方法第一行执行了createStore(...args),则接着去执行compose(e1, e2, e3)(createStore)(reducer, preloadedState),即先处理enhancer,处理完,在进行Middleware的处理(它的处理需要dispatch(action)),下面用实例来说明:
let e1 = (createStore) => (reducer, preloadedState) => {
console.log('e1');
let store = createStore(reducer, preloadedState);
console.log('e1-after');
return {
...store
}
}
let e2 = (createStore) => (reducer, preloadedState) => {
console.log('e2');
let store = createStore(reducer, preloadedState);
console.log('e2-after');
return {
...store
}
}
let e3 = (createStore) => (reducer, preloadedState) => {
console.log('e3');
let store = createStore(reducer, preloadedState);
console.log('e3-after');
return {
...store
}
}
let m1 = ({getState, dispatch}) => (next) => (action) => {
console.log('m1');
next(action);
console.log('m1-after');
}
let m2 = ({getState, dispatch}) => (next) => (action) => {
console.log('m2');
next(action);
console.log('m2-after');
}
let m3 = ({getState, dispatch}) => (next) => (action) => {
console.log('m3');
next(action);
console.log('m3-after');
}
let enhancer = compose(e1, e2, e3);
let store = applyMiddleware(m1, m2, m3)(createStore)(reducer, enhancer);
执行结果:e1 e2 e3 e3-after e2-after e1-after 当触发action之后,打印出:m1 m2 m3 m3-after m2-after m1-after
2、当let store = createStore(reducer, preloadedState, compose(e1, e2, e3, applyMiddleware(m1, m2, m3)))时,执行结果一样。
如果在middleware中,又进行了dispatch(action),那middleware执行顺序如何
这种情况是针对异步情况,比如异步ajax请求。下面我们模拟这种情况,不过你在middleware中不能直接使用dispatch(action),如果直接使用,可能会产生死循环。因此在middleware中使用dispatch(action)时,要有一个条件判断,满足这个条件的,才能进行dispatch(action),要是无限满足,那就死循环了。
先进行一个实例:
let m1 = ({getState, dispatch}) => (next) => (action) => {
console.log('m1-next-before');
next(action);
console.log('m1-next-after');
}
let m2 = ({getState, dispatch}) => (next) => (action) => {
console.log('m2-next-before');
//当执行dispatch(action)时(保证isNotGo不为true),执行到此处时,会再次执行dispatch({type: 'CHESHI', isNotGo: true})
//不这样设置,可能会造成死循环
if(!action.isNotGo) {
dispatch({type: 'CHESHI', isNotGo: true});
}
next(action);
console.log('m2-next-after');
}
let m3 = ({getState, dispatch}) => (next) => (action) => {
console.log('m3-next-before');
next(action);
console.log('m3-next-after');
}
let store = applyMiddleware(m1, m2, m3)(createStore)(reducer);
触发dispatch(action)后,结果:
从实例中看出,当触发dispatch(action)时,执行m1-next-before,当运行到中间件m2时,输出m2-next-before,此时
判断出!action.isNotGo为true,会进行dispatch(action),程序将再次从m1开始,依次执行,等再次到m2时,!action.isNotGo
为false,不会再dispatch(action)了,则将执行到m3,即此时,结果应该是m1-next-before m2-next-before m1-next-before
m2-next-before m3-next-before m3-next-after m2-next-after m1-next-after,接着将继续从m2开始执行next(action),
输出:m3-next-before m3-next-after m2-next-after m1-next-after
标签:Enhancer,enhancer,next,源码,preloadedState,action,Redux,createStore,store 来源: https://blog.csdn.net/wangyuegyq/article/details/104895390