Skip to content

级联中间件 ​

本节目标:理解“级联中间件”的核心思路,并能把它用于实际开发或面试表达。

说明:原 OneNote 中有图片引用,但图片未包含在导出目录中;本页保留了可用的文字与代码内容。 目录划分:

  • 仓库store
  • 状态管理工具:redux
  • react状态管理工具:react-redux

修改

src/store/index.js
import

{

createStore,

applyMiddleware } from

'../redux';
import

rootReducer from

'./reducers';
import

promise from

'../redux-promise';
import

logger from

'../redux-logger';
import

thunk from

'../redux-thunk';
let

store =

applyMiddleware(thunk,
promise,
logger)(createStore)(rootReducer);
export

default

store;

这里的store,我们通过applyMiddleware源码了解,这个store包含了我们应用了中间件后的dispatch,和子store;

Promise thunk使用Src/store/actions/couter1.js中添加一个

action;
promiseAdd()

{return new

Promise((resolve,
reject)

=\> {/* fetch('/user.json').then(res=\>res.json()).then(res=\>{resolve({type:actionTypes.ADD1});});; */

setTimeout(()

=\> {let number =

Math.random();
   `if`
(number

\>=

.5)

{

resolve({

type:

actionTypes.ADD1

});} else {

resolve({

type:

actionTypes.ADD1

});}},

1000);
});
},

新建

src/redux-promise.js
/**

* dispatch 重新派发 * next 下一步 * @param {*} param0* @returns

*/
function
promise({
getState,

dispatch }) {return function

(next)
{//

调用下一个中间件 next=store.原始的dispatch方法 return function

(action)
{//

这个就是改造后的dispatchif

(action.then

&& typeof

action.then

===

'function')

{

action.then(dispatch).catch(dispatch);
   `}` `else` `if`
(action.payload

&& typeof

action.payload.then

===

'function')

{

action.payload
.then(payload

=\>

dispatch({
...action,

payload }))

.catch(error

=\> {

dispatch({
...action,

error:

true,

payload: error });return

Promise.reject(error);
       `})`
  `}` `else` `{`
next(action);
   `}`
`}`
}
}
export

default

promise;

在src/components/counter.js中添加一个按钮:

<button
onClick={thunkAdd}>thunkAdd</button>
<button
onClick={promiseAdd}>promiseAdd</button>

添加另外一种promise实现,之前返回一个函数的方式只能处理成功情况,不能处理失败情况;

Src/store/actions/counter1.js
promise2Add()

{return {type:

actionTypes.ADD1,
 `payload:` `new`
Promise((resolve,
reject)

=\> {

setTimeout(()

=\> {let number =

Math.random();
     `if`
(number

\>=

.5)

{

resolve(1);
     `}` `else` `{`
reject('

失败了

');
     `}`
  `},`
1000);
 `})`
}
}

在src/redux-promise.js,添加处理 /*** dispatch ==重新派发== * next ==下一步== * @param {*} param0* @returns

*/
function
promise({
getState,

dispatch }) {return function

(next)
{//

调用下一个中间件 next=store.原始的dispatch方法 return function

(action)
{//

这个就是改造后的dispatchif

(action.then

&& typeof

action.then

===

'function')

{

action.then(dispatch).catch(dispatch);
   `}` `else` `if`
(action.payload

&& typeof

action.payload.then

===

'function')

{

action.payload
.then(payload

=\>

dispatch({
...action,

payload }))

.catch(error

=\> {

dispatch({
...action,

error:

true,

payload: error });return

Promise.reject(error);
       `})`
  `}` `else` `{`
next(action);
   `}`
`}`
}
}
export

default

promise;
src\redux-thunk\index.js
function
thunk({
getState,

dispatch }) {return function

(next)
{//

调用下一个中间件 next=store.原始的dispatch方法 return function

(action)
{//

这个就是改造后的dispatchdebuggerif

(typeof

action ===

'function')

{return

action(dispatch,
getState);
   `}`
  `return`
next(action);//next=store.dispatch
 `}`
}
}
export

default

thunk;
Src/actions/conuter1.js
import

* as actionTypes from

'../action-types';
let

actions = {

add1()

{return { type:

actionTypes.ADD1

};},

minus1()

{return { type:

actionTypes.MINUS1

};},

changeColor(color)

{return { type:

actionTypes.CHANGE_COLOR,

payload: color };},

thunkAdd()

{return function

(dispatch,
getState)

{

setTimeout(()

=\> {

dispatch(new
Promise((resolve,
reject)

=\> {

setTimeout(()

=\> {let number =

Math.random();
         `if`
(number

\>=

.5)

{

resolve({

type:

actionTypes.ADD1

});} else {

resolve({

type:

actionTypes.ADD1

});}},

1000);
     `}));`
  `},`
1000);
 `}`

},

promiseAdd()

{return new

Promise((resolve,
reject)

=\> {/* fetch('/user.json').then(res=\>res.json()).then(res=\>{resolve({type:actionTypes.ADD1});});; */

setTimeout(()

=\> {let number =

Math.random();
     `if`
(number

\>=

.5)

{

resolve({

type:

actionTypes.ADD1

});} else {

resolve({

type:

actionTypes.ADD1

});}},

1000);
 `});`

},

promise2Add()

{return {type:

actionTypes.ADD1,
   `payload:` `new`
Promise((resolve,
reject)

=\> {

setTimeout(()

=\> {let number =

Math.random();
       `if`
(number

\>=

.5)

{

resolve(1);
       `}` `else` `{`
reject('

失败了

');
       `}`
    `},`
1000);
   `})`
`}`
}
}
export

default

actions;
Src/store/index.js
import

{

createStore,

applyMiddleware } from

'../redux';
import

rootReducer from

'./reducers';
import

promise from

'../redux-promise';
import

logger from

'../redux-logger';
import

thunk from

'../redux-thunk';
let

store =

applyMiddleware(thunk,
promise,
logger)(createStore)(rootReducer);
export

default

store;

修改

src/store/reducers/counter1.js
import
React,

{ Component } from

'react'
import

{ connect } from

'../react-redux';
import

actions from

'../store/actions/counter1';
import

* as actionTypes from

'../store/action-types';
//Counter1.props

=

{...state.counter1,...actions};
class

Counter1 extends Component {

render()

{let {

color,
number,
add1,
minus1,
changeColor,
thunkAdd,
promiseAdd,
   `promise2Add`
`}` `=`
this.props;
 `return` `(`
<div
style={{

color

}}>
<p>{number}</p>
<button
onClick={add1}>+</button>
<button
onClick={minus1}>-</button>
<button
onClick={()

=\>

changeColor('red')}>

改成红色

</button>
<button
onClick={thunkAdd}>thunkAdd</button>
<button
onClick={promiseAdd}>promiseAdd</button>
<button
onClick={promise2Add}>promise2Add</button>
</div>
 `)`
}
}
//

把仓库中的状态映射为组件的属性对象 输入 let mapStateToProps = state =\>

state.counter1;
//

把dispatch方法映射为一个属性对象 let mapDispatchToProps = dispath =\> ({

add1()

{

dispath({

type:

actionTypes.ADD1

});},

minus1()

{

dispath({

type:

actionTypes.MINUS1

});},

changeColor(color)

{

dispath({

type:

actionTypes.CHANGE_COLOR,

payload: color });

}
})
//

把派发的动作映射为属性对象 //let

mapDispatchToProps
export

default

connect(
mapStateToProps,

//mapDispatchToProps //第一种 actions //第二种

)(Counter1);
/**

* 组件关联仓库两个方向 * 输入 组件里使用仓库提供的状态进行组件的渲染 * 输出 在组件可以派发动作从而修改仓库中的状态

*/
compose
  • 如果一个函数需要经过多个函数处理才能得到最终值,这个时候可以把中间过程的函数合并一个函数;

src\redux\compose.js

  •   compose

function

add1(str)

{return '1' +

str;
}
function
add2(str)

{return '2' +

str;
}
function
add3(str)

{return '3' +

str;
}
function
compose(...funcs)

{return function

(args)

{for

(let

i =

funcs.length

-

1;

i \>=

0;
i--)

{args =

funcs[i](args);
 `}`
`return`
args;
}
}
function
compose(...funcs)

{return

funcs.reduce((a,
b)

=\>

(...args)

=\>

a(b(...args)));
}
/**
*

第一次 a=add3 b=add2 =\>

(...args)=>add3(add2(...args))
*

第二次 a=(...args)=\>add3(add2(...args)) b=add1 =\>

(...args)=>add3(add2((add1(...args)))))
*/let

fn =

compose(add3,
add2,
add1);
let

result =

fn('zhufeng');
console.log(result);

链式调用


function
compose(...funcs)

{return

funcs.reduce((a,
b)

=\>

(...args)

=\>

a(b(...args)));
}
let

promise =

(next)

=\> action =\> {

console.log('promise');
next(action);
};
let

thunk =

(next)

=\> action =\> {

console.log('thunk');
next(action);
};
let

logger =

(next)

=\> action =\> {

console.log('logger');
next(action);
};
let

chain =

[promise,
thunk,
logger];
let

composed =

compose(...chain)
let

dispatch = () =\> {

console.log('

原始的

dispatch');
}
let

newDispatch =

composed(dispatch);
newDispatch({

type: "add" });

本站总访问 — 次